Skip to content

Commit

Permalink
Support status codes other than 301 and 302 in RequestHandler.redirec…
Browse files Browse the repository at this point in the history
…t().

Closes tornadoweb#228.
Closes tornadoweb#424.
  • Loading branch information
bdarnell committed Dec 31, 2011
1 parent 7f5d4de commit ad63265
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
19 changes: 19 additions & 0 deletions tornado/test/web_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,16 @@ def get(self):
self.add_header("x-multi", 3)
self.add_header("x-multi", "4")

class RedirectHandler(RequestHandler):
def get(self):
if self.get_argument('permanent', None) is not None:
self.redirect('/', permanent=int(self.get_argument('permanent')))
elif self.get_argument('status', None) is not None:
self.redirect('/', status=int(self.get_argument('status')))
else:
raise Exception("didn't get permanent or status arguments")


class WebTest(AsyncHTTPTestCase, LogTrapTestCase):
def get_app(self):
loader = DictLoader({
Expand All @@ -348,6 +358,7 @@ def get_app(self):
url("/optional_path/(.+)?", OptionalPathHandler),
url("/flow_control", FlowControlHandler),
url("/multi_header", MultiHeaderHandler),
url("/redirect", RedirectHandler),
]
return Application(urls,
template_loader=loader,
Expand Down Expand Up @@ -433,6 +444,14 @@ def test_multi_header(self):
self.assertEqual(response.headers["x-overwrite"], "2")
self.assertEqual(response.headers.get_list("x-multi"), ["3", "4"])

def test_redirect(self):
response = self.fetch("/redirect?permanent=1", follow_redirects=False)
self.assertEqual(response.code, 301)
response = self.fetch("/redirect?permanent=0", follow_redirects=False)
self.assertEqual(response.code, 302)
response = self.fetch("/redirect?status=307", follow_redirects=False)
self.assertEqual(response.code, 307)


class ErrorResponseTest(AsyncHTTPTestCase, LogTrapTestCase):
def get_app(self):
Expand Down
16 changes: 13 additions & 3 deletions tornado/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,11 +410,21 @@ def get_secure_cookie(self, name, value=None, max_age_days=31):
return decode_signed_value(self.application.settings["cookie_secret"],
name, value, max_age_days=max_age_days)

def redirect(self, url, permanent=False):
"""Sends a redirect to the given (optionally relative) URL."""
def redirect(self, url, permanent=False, status=None):
"""Sends a redirect to the given (optionally relative) URL.
If the ``status`` argument is specified, that value is used as the
HTTP status code; otherwise either 301 (permanent) or 302
(temporary) is chosen based on the ``permanent`` argument.
The default is 302 (temporary).
"""
if self._headers_written:
raise Exception("Cannot redirect after headers have been written")
self.set_status(301 if permanent else 302)
if status is None:
status = 301 if permanent else 302
else:
assert isinstance(status, int) and 300 <= status <= 399
self.set_status(status)
# Remove whitespace
url = re.sub(b(r"[\x00-\x20]+"), "", utf8(url))
self.set_header("Location", urlparse.urljoin(utf8(self.request.uri),
Expand Down

0 comments on commit ad63265

Please sign in to comment.