From: Ben Darnell Date: Mon, 7 May 2012 07:18:55 +0000 (-0700) Subject: Fix handling of non-ascii data in reverse_url. X-Git-Tag: v2.3.0~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=28590fce120a42ee5f3f1a960040bd1cb84422cc;p=thirdparty%2Ftornado.git Fix handling of non-ascii data in reverse_url. Closes #490. --- diff --git a/tornado/test/web_test.py b/tornado/test/web_test.py index 40aafbc14..ff2f9f80b 100644 --- a/tornado/test/web_test.py +++ b/tornado/test/web_test.py @@ -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.*)", 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, diff --git a/tornado/web.py b/tornado/web.py index 8978d2d0b..ab6173790 100644 --- a/tornado/web.py +++ b/tornado/web.py @@ -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