]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Fix handling of non-ascii data in reverse_url.
authorBen Darnell <ben@bendarnell.com>
Mon, 7 May 2012 07:18:55 +0000 (00:18 -0700)
committerBen Darnell <ben@bendarnell.com>
Mon, 7 May 2012 07:18:55 +0000 (00:18 -0700)
Closes #490.

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

index 40aafbc1498ba4d5f87ed8490c6970f09ad95d34..ff2f9f80b56b6bd099ba80949fdc3d93863b781e 100644 (file)
@@ -442,7 +442,7 @@ class WebTest(AsyncHTTPTestCase, LogTrapTestCase):
                 })
         urls = [
             url("/typecheck/(.*)", TypeCheckHandler, name='typecheck'),
-            url("/decode_arg/(.*)", DecodeArgHandler),
+            url("/decode_arg/(.*)", DecodeArgHandler, name='decode_arg'),
             url("/decode_arg_kw/(?P<arg>.*)", DecodeArgHandler),
             url("/linkify", LinkifyHandler),
             url("/uimodule_resources", UIModuleResourceHandler),
@@ -453,10 +453,11 @@ class WebTest(AsyncHTTPTestCase, LogTrapTestCase):
             url("/empty_flush", EmptyFlushCallbackHandler),
             url("/header_injection", HeaderInjectionHandler),
             ]
-        return Application(urls,
-                           template_loader=loader,
-                           autoescape="xhtml_escape",
-                           cookie_secret=self.COOKIE_SECRET)
+        self.app = Application(urls,
+                               template_loader=loader,
+                               autoescape="xhtml_escape",
+                               cookie_secret=self.COOKIE_SECRET)
+        return self.app
 
     def fetch_json(self, *args, **kwargs):
         response = self.fetch(*args, **kwargs)
@@ -496,6 +497,16 @@ class WebTest(AsyncHTTPTestCase, LogTrapTestCase):
                                 u'query': [u'bytes', u'c3a9'],
                                 })
 
+    def test_reverse_url(self):
+        self.assertEqual(self.app.reverse_url('decode_arg', 'foo'),
+                         '/decode_arg/foo')
+        self.assertEqual(self.app.reverse_url('decode_arg', 42),
+                         '/decode_arg/42')
+        self.assertEqual(self.app.reverse_url('decode_arg', b('\xe9')),
+                         '/decode_arg/%E9')
+        self.assertEqual(self.app.reverse_url('decode_arg', u'\u00e9'),
+                         '/decode_arg/%C3%A9')
+
     def test_uimodule_unescaped(self):
         response = self.fetch("/linkify")
         self.assertEqual(response.body,
index 8978d2d0b14db38e07521f19c19c700571489884..ab61737904e03f74a4a2d8d5c02a6853478974a1 100644 (file)
@@ -1391,7 +1391,11 @@ class Application(object):
     def reverse_url(self, name, *args):
         """Returns a URL path for handler named `name`
 
-        The handler must be added to the application as a named URLSpec
+        The handler must be added to the application as a named URLSpec.
+
+        Args will be substituted for capturing groups in the URLSpec regex.
+        They will be converted to strings if necessary, encoded as utf8,
+        and url-escaped.
         """
         if name in self.named_handlers:
             return self.named_handlers[name].reverse(*args)
@@ -1955,7 +1959,12 @@ class URLSpec(object):
             "not found"
         if not len(args):
             return self._path
-        return self._path % tuple([str(a) for a in args])
+        converted_args = []
+        for a in args:
+            if not isinstance(a, (unicode, bytes_type)):
+                a = str(a)
+            converted_args.append(escape.url_escape(utf8(a)))
+        return self._path % tuple(converted_args)
 
 url = URLSpec