]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
feat: RedirectHandler to pass GET query 2109/head
authorYiliang Tang <ydatylmonv@gmail.com>
Sat, 17 Jun 2017 06:09:05 +0000 (14:09 +0800)
committerYiliang Tang <ydatylmonv@gmail.com>
Sun, 16 Jul 2017 14:04:49 +0000 (22:04 +0800)
tornado/httputil.py
tornado/test/httputil_test.py
tornado/test/web_test.py
tornado/web.py

index 5b87ce61020f83e0a4d972d483720244fa711423..a98273aec0ed13099aa97ef35876b76783edc338 100755 (executable)
@@ -942,6 +942,14 @@ def split_host_and_port(netloc):
     return (host, port)
 
 
+def qs_to_qsl(qs):
+    """Generator rewinding a result of ``parse_qs`` back to name-value pairs. 
+    """
+    for k, vs in qs.items():
+        for v in vs:
+            yield (k, v)
+
+
 _OctalPatt = re.compile(r"\\[0-3][0-7][0-7]")
 _QuotePatt = re.compile(r"[\\].")
 _nulljoin = ''.join
index d1278567bbcd4c3c770620d8b6dfd20b4069b20f..7ac79925723e6bdc2327164578fd331a1d189717 100644 (file)
@@ -3,7 +3,7 @@
 
 
 from __future__ import absolute_import, division, print_function
-from tornado.httputil import url_concat, parse_multipart_form_data, HTTPHeaders, format_timestamp, HTTPServerRequest, parse_request_start_line, parse_cookie
+from tornado.httputil import url_concat, parse_multipart_form_data, HTTPHeaders, format_timestamp, HTTPServerRequest, parse_request_start_line, parse_cookie, qs_to_qsl, PY3
 from tornado.escape import utf8, native_str
 from tornado.log import gen_log
 from tornado.testing import ExpectLog
@@ -15,6 +15,11 @@ import logging
 import pickle
 import time
 
+if PY3:
+    import urllib.parse as urllib_parse
+else:
+    import urlparse as urllib_parse
+
 
 class TestUrlConcat(unittest.TestCase):
     def test_url_concat_no_query_params(self):
@@ -102,6 +107,17 @@ class TestUrlConcat(unittest.TestCase):
         self.assertEqual(url, "https://localhost/path?y=y")
 
 
+class QsParseTest(unittest.TestCase):
+
+    def test_parsing(self):
+        qsstring = "a=1&b=2&a=3"
+        qs = urllib_parse.parse_qs(qsstring)
+        qsl = list(qs_to_qsl(qs))
+        self.assertIn(('a', '1'), qsl)
+        self.assertIn(('a', '3'), qsl)
+        self.assertIn(('b', '2'), qsl)
+
+
 class MultipartFormDataTest(unittest.TestCase):
     def test_file_upload(self):
         data = b"""\
index ffccc02d370c51a8be10eb64d2b5af6b16913717..7c33fd9015ac49d027820f7a58d8513fbd4f9d0e 100644 (file)
@@ -2880,6 +2880,7 @@ class RedirectHandlerTest(WebTestCase):
     def get_handlers(self):
         return [
             ('/src', WebRedirectHandler, {'url': '/dst'}),
+            ('/src2', WebRedirectHandler, {'url': '/dst2?foo=bar'}),
             (r'/(.*?)/(.*?)/(.*)', WebRedirectHandler, {'url': '/{1}/{0}/{2}'})]
 
     def test_basic_redirect(self):
@@ -2887,6 +2888,16 @@ class RedirectHandlerTest(WebTestCase):
         self.assertEqual(response.code, 301)
         self.assertEqual(response.headers['Location'], '/dst')
 
+    def test_redirect_with_argument(self):
+        response = self.fetch('/src?foo=bar', follow_redirects=False)
+        self.assertEqual(response.code, 301)
+        self.assertEqual(response.headers['Location'], '/dst?foo=bar')
+
+    def test_redirect_with_appending_argument(self):
+        response = self.fetch('/src2?foo2=bar2', follow_redirects=False)
+        self.assertEqual(response.code, 301)
+        self.assertEqual(response.headers['Location'], '/dst2?foo=bar&foo2=bar2')
+
     def test_redirect_pattern(self):
         response = self.fetch('/a/b/c', follow_redirects=False)
         self.assertEqual(response.code, 301)
index defd216182d9485257dd0c7497ca105d88d25dfe..0cc34b8e4b9e07bd84dbd2101044283f28e9eff6 100644 (file)
@@ -2279,7 +2279,11 @@ class RedirectHandler(RequestHandler):
         self._permanent = permanent
 
     def get(self, *args):
-        self.redirect(self._url.format(*args), permanent=self._permanent)
+        to_url = self._url.format(*args)
+        if self.request.query_arguments:
+            to_url = httputil.url_concat(
+                to_url, list(httputil.qs_to_qsl(self.request.query_arguments)))
+        self.redirect(to_url, permanent=self._permanent)
 
 
 class StaticFileHandler(RequestHandler):