Skip to content


Subversion checkout URL

You can clone with
Download ZIP


Add support for RFC5988 Link header #528

wants to merge 1 commit into from

2 participants


Add, RequestHandler.hint. This allows applications to easily hint to the client which resources are related to a response, to cut down on request latency, as recommended by

@alekstorm alekstorm Add support for RFC5988 Link header
Add, RequestHandler.hint

I'm not sure that these headers really warrant special methods; I'd
rather not establish a precedent of methods to construct values for
every nontrivial header. I definitely think hint is unnecessary; link is just
complicated enough that I can see some value (although the name is too
vague and likely to collide with names used in subclasses). Except
for the angle brackets around the url, this could be done with an
extension of set_header that supports the semicolon-delimited options
seen in many headers.

Also, why a list of pairs instead of a dict? Are there cases where
duplicates are allowed or order matters? I'd prefer to support dicts
for the common case, with lists of pairs as an option if needed.


Yeah, I suspected there might be subtle differences in the different header syntaxes. Do you think there's enough commonality that a shared implementation would be useful?

There is precedent for type-checking to allow either dicts or lists of pairs as arguments (the examples that come to mind are the dict constructor itself and urllib.urlencode). I think type-checking would be more pythonic than a dict of lists, since a dict of lists impacts every call even when the common case is a one-to-one mapping.

@bdarnell bdarnell added the web label
@bdarnell bdarnell closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 4, 2012
  1. @alekstorm

    Add support for RFC5988 Link header

    alekstorm committed
    Add, RequestHandler.hint
This page is out of date. Refresh to see the latest.
Showing with 29 additions and 0 deletions.
  1. +11 −0 tornado/test/
  2. +18 −0 tornado/
11 tornado/test/
@@ -436,6 +436,12 @@ def get(self):
+class LinkHandler(RequestHandler):
+ def get(self):
+"", [('rel', '"previous"'), ('title', '"previous chapter"')])
+ self.hint("/hinted")
class WebTest(AsyncHTTPTestCase, LogTrapTestCase):
@@ -464,6 +470,7 @@ def get_app(self):
url("/redirect", RedirectHandler),
url("/empty_flush", EmptyFlushCallbackHandler),
url("/header_injection", HeaderInjectionHandler),
+ url("/link", LinkHandler),
] = Application(urls,
@@ -579,6 +586,10 @@ def test_header_injection(self):
response = self.fetch("/header_injection")
self.assertEqual(response.body, b("ok"))
+ def test_link(self):
+ response = self.fetch("/link")
+ self.assertEqual(response.headers["Link"], '<>;rel="previous";title="previous chapter",</hinted>;rel="subresource"')
class ErrorResponseTest(AsyncHTTPTestCase, LogTrapTestCase):
def get_app(self):
18 tornado/
@@ -447,6 +447,24 @@ def get_secure_cookie(self, name, value=None, max_age_days=31):
return decode_signed_value(self.application.settings["cookie_secret"],
name, value, max_age_days=max_age_days)
+ def link(self, uri, params):
+ """Add a link to the Link header. See
+ for a description.
+ :arg string uri: URI of the link
+ :arg list params: List of (name, value) link parameters
+ """
+ self.add_header('Link', ('<%s>;' % uri)+';'.join(['%s=%s' % pair for pair in params]))
+ def hint(self, uri, rel='"subresource"'):
+ """Convenience function for hinting to the client that the given URI
+ is related to this resource.
+ :arg string uri: URI of the link
+ :arg string rel: Relation type of the link
+ """
+, [('rel', rel)])
def redirect(self, url, permanent=False, status=None):
"""Sends a redirect to the given (optionally relative) URL.
Something went wrong with that request. Please try again.