Skip to content

Commit

Permalink
Merge pull request tornadoweb#1867 from ajdavis/redirecthandler-url-p…
Browse files Browse the repository at this point in the history
…attern

web: Add regex support to RedirectHandler
  • Loading branch information
ajdavis authored Nov 5, 2016
2 parents 3d2bcbe + ef6957d commit 9bdc317
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 3 deletions.
2 changes: 1 addition & 1 deletion docs/guide/structure.rst
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ to the prefix ``/photos/`` instead::
app = tornado.web.Application([
url(r"/photos/(.*)", MyPhotoHandler),
url(r"/pictures/(.*)", tornado.web.RedirectHandler,
dict(url=r"/photos/\1")),
dict(url=r"/photos/{0}")),
])

Unlike `.RequestHandler.redirect`, `.RedirectHandler` uses permanent
Expand Down
17 changes: 17 additions & 0 deletions tornado/test/web_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2866,3 +2866,20 @@ def test_non_reversible(self):
def test_reverse_arguments(self):
self.assertEqual('/api/v1/foo/bar',
url(r'^/api/v1/foo/(\w+)$', None).reverse('bar'))


class RedirectHandlerTest(WebTestCase):
def get_handlers(self):
return [
('/src', WebRedirectHandler, {'url': '/dst'}),
(r'/(.*?)/(.*?)/(.*)', WebRedirectHandler, {'url': '/{1}/{0}/{2}'})]

def test_basic_redirect(self):
response = self.fetch('/src', follow_redirects=False)
self.assertEqual(response.code, 301)
self.assertEqual(response.headers['Location'], '/dst')

def test_redirect_pattern(self):
response = self.fetch('/a/b/c', follow_redirects=False)
self.assertEqual(response.code, 301)
self.assertEqual(response.headers['Location'], '/b/a/c')
20 changes: 18 additions & 2 deletions tornado/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -2191,13 +2191,29 @@ class RedirectHandler(RequestHandler):
application = web.Application([
(r"/oldpath", web.RedirectHandler, {"url": "/newpath"}),
])
`RedirectHandler` supports regular expression substitutions. E.g., to
swap the first and second parts of a path while preserving the remainder::
application = web.Application([
(r"/(.*?)/(.*?)/(.*)", web.RedirectHandler, {"url": "/{1}/{0}/{2}"}),
])
The final URL is formatted with `str.format` and the substrings that match
the capturing groups. In the above example, a request to "/a/b/c" would be
formatted like::
str.format("/{1}/{0}/{2}", "a", "b", "c") # -> "/b/a/c"
Use Python's :ref:`format string syntax <formatstrings>` to customize how
values are substituted.
"""
def initialize(self, url, permanent=True):
self._url = url
self._permanent = permanent

def get(self):
self.redirect(self._url, permanent=self._permanent)
def get(self, *args):
self.redirect(self._url.format(*args), permanent=self._permanent)


class StaticFileHandler(RequestHandler):
Expand Down

0 comments on commit 9bdc317

Please sign in to comment.