Post data lost on 301 Moved Permanently

May 15th, 2009 by Julien Palard

What the hell with 301 Moved Permanently HTTP header !?

I’ll take an exemple to explain my ugly problem, take, a [very ugly cause it's PHP] index.php, it could be retrieved by using :
http://example.com/directory/index.php
-> Got the page, 200 OK
or http://example.com/directory/
-> Got the page, 200 OK
or http://example.com/directory
-> Got a 301 Moved Permanently Location: http://example.com/directory/

Just like expected … but…

As you can see, on the captured HTTP headers below, when you POST data on a 301 target, you’ll be redirected, but unfortunately you’ll lost your POST data, even worse, your request can be reforged as a GET request !


Let me show you an example :
Request :

POST /directory HTTP/1.1
Host: example.com
[user agent, referer, cache control, origin, content type, accept, accept-encoding, blah blah ...]
Content-Length: 7

foo=bar

Response :

HTTP/1.0 301 Moved Permanently
Location: http://example.com/directory/
[... blah blah]

Reforged request :

GET /directory/ HTTP/1.1
Host: example.com

Why my data isn’t kept in the reforged one !?

So let’s read The RFC 2616 (about HTTP …)

10.3.2 301 Moved Permanently

[...]

The new permanent URI SHOULD be given by the Location field in the
response. Unless the request method was HEAD, the entity of the
response SHOULD contain a short hypertext note with a hyperlink to
the new URI(s).

If the 301 status code is received in response to a request other
than GET or HEAD, the user agent MUST NOT automatically redirect the
request unless it can be confirmed by the user, since this might
change the conditions under which the request was issued.

Note: When automatically redirecting a POST request after
receiving a 301 status code, some existing HTTP/1.0 user agents
will erroneously change it into a GET request.

Ahh, ok, so, for request other than GET or HEAD, the user agent MUST NOT automatically redirect to the request ? Ugh, it’s not the case in IE 6, 7, 8, Firefox, nor Chrome.
And, about the security, while the server recieves the data, it can do everything, for example send it to another server directly.
Then I’m wondering, why asking to the user if he allows his data to be transfered ?

Then, the RFC says an interesting thing …

Note: When automatically redirecting a POST request after
receiving a 301 status code, some existing HTTP/1.0 user agents
will erroneously change it into a GET request.

But, not only HTTP/1.0 user agents, but HTTP/1.1 user agents like browsers and frameworks (as, I encountred the problem firstly in the .NET Framework 3.5, in HttpWebRequest) )o:

OK, end of this article, have a nice day )o’,:

Leave a Reply