Skip to content

Commit

Permalink
simple_httpclient: Treat 302 like 303.
Browse files Browse the repository at this point in the history
Cherry-picked from bergundy@e49b263

Closes #623.
  • Loading branch information
bdarnell committed Nov 1, 2012
1 parent 81475d5 commit ff343ae
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 17 deletions.
9 changes: 7 additions & 2 deletions tornado/simple_httpclient.py
Expand Up @@ -409,8 +409,13 @@ def _on_body(self, data):
new_request.max_redirects -= 1
del new_request.headers["Host"]
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4
# client SHOULD make a GET request
if self.code == 303:
# Client SHOULD make a GET request after a 303.
# According to the spec, 302 should be followed by the same
# method as the original request, but in practice browsers
# treat 302 the same as 303, and many servers use 302 for
# compatibility with pre-HTTP/1.1 user agents which don't
# understand the 303 status.
if self.code in (302, 303):
new_request.method = "GET"
new_request.body = None
for h in ["Content-Length", "Content-Type",
Expand Down
31 changes: 16 additions & 15 deletions tornado/test/simple_httpclient_test.py
Expand Up @@ -74,15 +74,15 @@ def get(self):
self.set_status(204)


class SeeOther303PostHandler(RequestHandler):
class SeeOtherPostHandler(RequestHandler):
def post(self):
if self.request.body != b("blah"):
raise Exception("unexpected body %r" % self.request.body)
self.set_header("Location", "/303_get")
self.set_status(303)
redirect_code = int(self.request.body)
assert redirect_code in (302, 303), "unexpected body %r" % self.request.body
self.set_header("Location", "/see_other_get")
self.set_status(redirect_code)


class SeeOther303GetHandler(RequestHandler):
class SeeOtherGetHandler(RequestHandler):
def get(self):
if self.request.body:
raise Exception("unexpected body %r" % self.request.body)
Expand Down Expand Up @@ -113,8 +113,8 @@ def get_app(self):
url("/head", HeadHandler),
url("/options", OptionsHandler),
url("/no_content", NoContentHandler),
url("/303_post", SeeOther303PostHandler),
url("/303_get", SeeOther303GetHandler),
url("/see_other_post", SeeOtherPostHandler),
url("/see_other_get", SeeOtherGetHandler),
url("/host_echo", HostEchoHandler),
], gzip=True)

Expand Down Expand Up @@ -201,13 +201,14 @@ def test_header_reuse(self):
self.fetch("/hello", headers=headers)
self.assertEqual(list(headers.get_all()), [('User-Agent', 'Foo')])

def test_303_redirect(self):
response = self.fetch("/303_post", method="POST", body="blah")
self.assertEqual(200, response.code)
self.assertTrue(response.request.url.endswith("/303_post"))
self.assertTrue(response.effective_url.endswith("/303_get"))
#request is the original request, is a POST still
self.assertEqual("POST", response.request.method)
def test_see_other_redirect(self):
for code in (302, 303):
response = self.fetch("/see_other_post", method="POST", body="%d" % code)
self.assertEqual(200, response.code)
self.assertTrue(response.request.url.endswith("/see_other_post"))
self.assertTrue(response.effective_url.endswith("/see_other_get"))
#request is the original request, is a POST still
self.assertEqual("POST", response.request.method)

def test_request_timeout(self):
with ExpectLog(gen_log, "uncaught exception"):
Expand Down

0 comments on commit ff343ae

Please sign in to comment.