]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Support status codes other than 301 and 302 in RequestHandler.redirect().
authorBen Darnell <ben@bendarnell.com>
Sat, 31 Dec 2011 04:20:25 +0000 (20:20 -0800)
committerBen Darnell <ben@bendarnell.com>
Sat, 31 Dec 2011 04:20:25 +0000 (20:20 -0800)
Closes #228.
Closes #424.

tornado/test/web_test.py
tornado/web.py

index c5ae99a37784007031676824581f7677bab0953b..fccd3fc1d15234fa83023879c56e2b3be2b6be10 100644 (file)
@@ -325,6 +325,16 @@ class MultiHeaderHandler(RequestHandler):
         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({
@@ -348,6 +358,7 @@ class WebTest(AsyncHTTPTestCase, LogTrapTestCase):
             url("/optional_path/(.+)?", OptionalPathHandler),
             url("/flow_control", FlowControlHandler),
             url("/multi_header", MultiHeaderHandler),
+            url("/redirect", RedirectHandler),
             ]
         return Application(urls,
                            template_loader=loader,
@@ -433,6 +444,14 @@ js_embed()
         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):
index dfafbcc346125a4677fc09f60fb3607972967aae..b403afe24b057af52debf0c8d35159e7b4bfa7e5 100644 (file)
@@ -410,11 +410,21 @@ class RequestHandler(object):
         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),