From 28590fce120a42ee5f3f1a960040bd1cb84422cc Mon Sep 17 00:00:00 2001 From: Ben Darnell Date: Mon, 7 May 2012 00:18:55 -0700 Subject: [PATCH] Fix handling of non-ascii data in reverse_url. Closes #490. --- tornado/test/web_test.py | 21 ++++++++++++++++----- tornado/web.py | 13 +++++++++++-- 2 files changed, 27 insertions(+), 7 deletions(-) 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 -- 2.47.2