73 lines
3.1 KiB
Markdown
73 lines
3.1 KiB
Markdown
Title: Post data lost on 301 Moved Permanently
|
|
|
|
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, ...]
|
|
Content-Length: 7 foo=bar
|
|
|
|
Response:
|
|
|
|
HTTP/1.0 301 Moved Permanently
|
|
Location: http://example.com/directory/
|
|
...
|
|
|
|
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:
|
|
|
|
Reforging as a GET is clearly not a good idea, but on the other hand,
|
|
as `POST` requests are not idempotent, we're still happy they're not
|
|
executed twice: Imagine the POST is "Pay for that shiny new laptop",
|
|
the payment is executed, but later in the request execution, a 301 to
|
|
another server is generated, if your client re-POST the same request
|
|
on the other server, your payment may be executed
|
|
twice... outch. Respecting idempotency looks clearly more important
|
|
than generating dumb `GET`, harmless, requests.
|
|
|
|
Hope it helps...
|