fix subsequent redirect request method type

E.g., after a POST with a 302 response, we should do a GET. This is how all browsers do it for historical reasons. And some websites even don't work otherwise.

See also: http://stackoverflow.com/questions/8138137/http-post-request-receives-a-302-should-the-redirect-request-be-a-get


1. If elegance (among other things) means adhering to the spec then according to [10.3.3](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3) of rfc2616 _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._
2. The url in your code is 129 chars long and putting it in one line is against pep8. You can omit question's title from the stackoverflow's url (as a bonus you are not dependent on question's title anymore) so in this case http://stackoverflow.com/questions/8138137/#8138447 would work the same.


@piotr-dobrogost: exactly. That is exactly why `allow_redirects` was added — and is set to `False` for POST requests. If the user explicitly sets it to `True`, then the redirect will be followed.


@kennethreitz: You mean `allow_redirects`?

You should read [this piece](http://codesearch.google.com/#OAMlx_jo-ck/src/net/url_request/url_request.cc&l=701) of the Google Chrome code:

```
  // For 303 redirects, all request methods except HEAD are converted to GET,
  // as per the latest httpbis draft.  The draft also allows POST requests to
  // be converted to GETs when following 301/302 redirects, for historical
  // reasons. Most major browsers do this and so shall we.  Both RFC 2616 and
  // the httpbis draft say to prompt the user to confirm the generation of new
  // requests, other than GET and HEAD requests, but IE omits these prompts and
  // so shall we.
  // See:  https://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-17#section-7.3
  bool was_post = method_ == "POST";
  if ((http_status_code == 303 && method_ != "HEAD") ||
      ((http_status_code == 301 || http_status_code == 302) && was_post)) {
    method_ = "GET";
    upload_ = NULL;
    if (was_post) {
      // If being switched from POST to GET, must remove headers that were
      // specific to the POST and don't have meaning in GET. For example
      // the inclusion of a multipart Content-Type header in GET can cause
      // problems with some servers:
      // http://code.google.com/p/chromium/issues/detail?id=843
      StripPostSpecificHeaders(&extra_request_headers_);
    }
  }
```

This is also how all other browsers are doing it. I think it makes more sense to follow that instead of doing it different than everybody else.

Also, as said, some websites/servers even break otherwise because they expect this behavior. (They return 302 instead of a 303 because 303 was too less supported a while ago and browsers do the expected behavior on 302 anyway.)

Also, it was reported [here](https://github.com/szechuen/CCC-Presale/issues/3#issuecomment-2759174) that Requests indeed did it that way a while ago, at least in 0.7.4. It just broke since 0.8.0.


If it was working in an older version of requests, that was a bug. Part of the hideousness that way building on top of urllib2 was not knowing exactly how the redirect handling worked. 


Only 303 responses should be treated this way.

Please see http://tools.ietf.org/html/rfc1945. 


If every major HTTP implementation has agreed to handle this not as in the specs, Requests shouldn't be the only HTTP implementation which behaves different (and thus breaks for some services).


Hmm. Alright, let's see what cURL does.


Albert's question on Stackoverflow [HTTP: POST request receives a 302, should the redirect-request be a GET?](http://stackoverflow.com/questions/8138137/) was [answered](http://stackoverflow.com/q/8139246/95735) by Julian Reschke who points to [ticket 160](http://trac.tools.ietf.org/wg/httpbis/trac/ticket/160) of httbis working group. In [comment 29](http://trac.tools.ietf.org/wg/httpbis/trac/ticket/160#comment:29) of this ticket there's a link to [changeset 1428](http://trac.tools.ietf.org/wg/httpbis/trac/changeset/1428) which **allows POST->GET rewriting for 301/302**. In light of this I think Requests should follow current UAs' behavior in regard to rewriting POST to GET for 301 and 302 status codes. This, according to section 7.3 of the [latest](http://trac.tools.ietf.org/wg/httpbis/trac/export/1428/draft-ietf-httpbis/latest/p2-semantics.html) (1428) draft of _HTTP/1.1, part 2: Message Semantics_, also means that redirect can be carried out **without** user intervention because GET method is idempotent.


Let's see what `curl` does.


> C:\Users\Piotr>curl -v -d "a=b" -L http://httpbin.org/redirect/1
> - About to connect() to httpbin.org port 80 (#0)
> -   Trying 173.230.131.235... connected
>   > POST /redirect/1 HTTP/1.1
>   > User-Agent: curl/7.23.1 (x86_64-pc-win32) libcurl/7.23.1 OpenSSL/0.9.8r zlib/1.2.5
>   > Host: httpbin.org
>   > Accept: _/_
>   > Content-Length: 3
>   > Content-Type: application/x-www-form-urlencoded
>   >
> - upload completely sent off: 3 out of 3 bytes
>   < HTTP/1.1 301 Moved Permanently
>   < Date: Sun, 27 Nov 2011 10:15:58 GMT
>   < Status: 301 Moved Permanently
>   < Connection: close
>   < Location: http://www.httpbin.org/redirect/1
>   < Content-Type: text/html
>   <
> - Closing connection #0
> - Issue another request to this URL: 'http://www.httpbin.org/redirect/1'
> - Violate RFC 2616/10.3.2 and switch from POST to GET
> - About to connect() to www.httpbin.org port 80 (#0)
> -   Trying 107.22.180.255... connected
>   > GET /redirect/1 HTTP/1.1
>   > User-Agent: curl/7.23.1 (x86_64-pc-win32) libcurl/7.23.1 OpenSSL/0.9.8r zlib/1.2.5
>   > Host: www.httpbin.org
>   > Accept: _/_


### Proposal
1. Non-safe methods still have `allow_redirects` default to `False`.
2. A new config setting called `strict_mode` will be set to `False` by default.
3. If `strict_mode` is `False`, a 301'd `POST` will follow the browser behavior.
4. If `strict_mode` is `True`, a 301'd `POST` will follow the RFC behavior.


What about `allow_redirects` defaulting to `not strict_mode` for non-safe methods?


I think that `strict_mode` should default to`True`.

In general I prefer software to do things the correct way, even if that correct way breaks when other people do things incorrectly. However I also prefer it when software that does do things the correct way gives me the flexibility to relax the restrictions in order to handle the case of someone else doing it wrong.

In general I think that doing something that violates the spec/RFC/standard etc should require being explicitly allowed which will not only make the consumers of poorly written web sites reflect upon, and maybe find a better way of doing something within the specs, but can also be a trigger to the websites to fix their site to work within the RFC. Which the web as a whole is a much better place when places follow the standards.


@dstufft: It's quite common to send 302 redirects after a successful POST. Perhaps you could argue that sites doing this are technically broken, but it's how many sites currently work. And it's how many popular frameworks, such as Django, suggest on handling successful POSTs.

I'm all for doing things "the right way". But I get the feeling that `strict_mode` will be set to `False` more often than not.


> In general I prefer software to do things the correct way, even if that correct way breaks when other people do things incorrectly.

The latest draft of new http specification (called httpbis) in section [7.3.3 302 Found](http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-17#section-7.3.3) states

```
Note: For historic reasons, user agents MAY change the request
method from POST to GET for the subsequent request.  If this
behavior is undesired, status code 307 (Temporary Redirect) can be
used instead.
```

So assuming it will obsolete current http spec (RFC 2616) the behavior with `strict_mode` set to `False` will be **conforming**.
Having said this, I think introducing `strict_mode` is unnecessary as behavior that will be implemented is de facto standard and in the (hopefully near) future will be de jury standard.


@piotr-dobrogost thanks for the research. That's compelling.


I've been bitten by this for exactly the reasons @andymccurdy mentions, that frameworks like Django give 302 redirects. Could we at least add a note in the docs on this?


Fine, lets do it. :)


Thanks guys. :)