Preventing form re-submission with HTTP 303 redirects
tumblr.jonthornton.com
tumblr.jonthornton.com
A proxy shouldn't care about a status code in the 300 range, but it might (maybe erroring out on "unknown" codes as part of some security feature).
And then there are scripts quickly thrown together using the HTTP libraries of $LANGUAGE. You'd have to check these too if you use them in a context where you'd also use a 303 redirect.
For what it's worth: my app is serving pages to users behind the worst possible collections of both enterprise and personal firewalls that seem to mangle HTTP headers at will. Heck, I even have more than 10% IE 5.5 users on one installation.
That said, ever since 2004 I have never had one instance of a browser or proxy resubmitting a form in response to a 302 redirect. But many instances of where leaving the trodden path, was causing the strangest unexpected breakages due to severely broken client software.
As such, personally, I will stay with what works and what the RFC is admitting to generally work even if it shouldn't, instead of experimenting with semantics for no visible gain what so ever.
Sounding bitter? Once you witness AV software altering Content-Encoding headers without altering the encoding, you too would get bitter :-)
The last UA I saw that didn't support 303 was Netscape 4.
Body of the redirect response should contain a link to the new page. This way even time travellers form '90s will be able to reach the destination page.
"If the 302 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."
Does the browser you use do that?
As with cookies, developers go with what works, even if it isn't exactly what the spec says.
History aside, it could be that there is now a difference in how 302 and 303 are interpreted by modern browsers, and I would love to see definitive tests. Any volunteers?
Granted there aren't many people running old versions of Firefox, but why risk it? Even if 302 is generally interpreted like a 303, it's safer to just use a 303.
RFC 2616 mentions early misinterpretations; they are why 303 and 307 exist:
"Note: RFC 1945 and RFC 2068 specify that the client is not allowed to change the method on the redirected request. However, most existing user agent implementations treat 302 as if it were a 303 response, performing a GET on the Location field-value regardless of the original request method. The status codes 303 and 307 have been added for servers that wish to make unambiguously clear which kind of reaction is expected of the client."
Recommending 303 sounds like a great idea, but the spec's description of 303 is what 302 is in practice, and the latest spec (2616) makes note of this reality. Also, consistent support for 303 is not a sure bet:
"Note: Many pre-HTTP/1.1 user agents do not understand the 303 status. When interoperability with such clients is a concern, the 302 status code may be used instead, since most user agents react to a 302 response as described here for 303."
Without evidence, using 303 is the riskier option.
The fact is there really aren't any pre-HTTP/1.1 browsers still in use. See: http://serverfault.com/questions/110932/are-there-internet-u...
Given that many web apps these days require javascript and CSS and HTTP/1.1 is over 12 years old, I don't think it's realistic to worry about clients that only support HTTP/1.0.
While 302 works in practice, it's safer to use 303, which works by definition.
As your StackOverflow link mentions, Squid, a widely used proxy, is still only fully implemented for HTTP/1.0.
Today all clients that send HTTP/1.0 version support more than HTTP/1.0, e.g. HTTP/1.1 Host header is basically mandatory on the web.
HTTP/1.1 compliance requires some harder things like pipelining support, and full HTTP/1.1 caching proxy has a lot of hairy stuff to deal with (strong/weak cache validators, stitching of partial responses, Vary support, etc.).
You can have quite decent HTTP/1.1 implementation that still doesn't deserve to be called full HTTP/1.1.
This is very pedantic of me, but as of HTTP 1.1, HTTP 302 is Found, not Temporarily Moved[1].
One question I found on a cursory search just now[1] asks whether to use 302 or 303. All three answers submitted to the question recommend 302. The key consideration seems to be backwards compatibility with HTTP 1.0 (the 303 response was apparently added for HTTP 1.1), with the understanding that 302s act close enough to 303s that you don't really need to worry about it. Is this a valid concern, or is this simply an old concern that hasn't died even though the context has changed over the years?
The bigger concern I have is that it allows clients to prompt user and re-send POST after 302 (exactly what the redirect trick is trying to prevent).
http://hg.python.org/cpython/file/0752215f9f91/Lib/urllib.py...
This is another reminder that I should really read the HTTP/1.1 spec someday.
It could definitely stand to be a bit more subtle, though.
I also usually put an exit() after redirects, just in case.