]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Allow non-standard HTTP codes to be passed with HTTPError.
authorBen Darnell <ben@bendarnell.com>
Mon, 24 Sep 2012 04:13:25 +0000 (00:13 -0400)
committerBen Darnell <ben@bendarnell.com>
Mon, 24 Sep 2012 04:13:25 +0000 (00:13 -0400)
tornado/test/web_test.py
tornado/web.py

index 8cb6af2ad3159b72f57807125b086d388af07df1..c602ba6231647cc7f9770b71fc5b78fcfd5b3f86 100644 (file)
@@ -933,3 +933,23 @@ class DateHeaderTest(SimpleHandlerTestCase):
         self.assertTrue(header_date - datetime.datetime.utcnow() <
                         datetime.timedelta(seconds=2))
 wsgi_safe.append(DateHeaderTest)
+
+
+class RaiseWithReasonTest(SimpleHandlerTestCase):
+    class Handler(RequestHandler):
+        def get(self):
+            raise HTTPError(682, reason="Foo")
+
+    def get_http_client(self):
+        # simple_httpclient only: curl doesn't expose the reason string
+        return SimpleAsyncHTTPClient(io_loop=self.io_loop)
+
+    def test_raise_with_reason(self):
+        response = self.fetch("/")
+        self.assertEqual(response.code, 682)
+        self.assertEqual(response.reason, "Foo")
+        self.assertIn(b('682: Foo'), response.body)
+
+    def test_httperror_str(self):
+        self.assertEqual(str(HTTPError(682, reason="Foo")), "HTTP 682: Foo")
+wsgi_safe.append(RaiseWithReasonTest)
index 92e94d3686da4b79334ad1e1320faec83b3a4532..87b52e926397ac1b3b40713cbee8eb799fa61d31 100644 (file)
@@ -752,7 +752,13 @@ class RequestHandler(object):
                 self.finish()
             return
         self.clear()
-        self.set_status(status_code)
+
+        reason = None
+        if 'exc_info' in kwargs:
+            exception = kwargs['exc_info'][1]
+            if isinstance(exception, HTTPError) and exception.reason:
+                reason = exception.reason
+        self.set_status(status_code, reason=reason)
         try:
             self.write_error(status_code, **kwargs)
         except Exception:
@@ -801,7 +807,7 @@ class RequestHandler(object):
             self.finish("<html><title>%(code)d: %(message)s</title>"
                         "<body>%(code)d: %(message)s</body></html>" % {
                     "code": status_code,
-                    "message": httplib.responses[status_code],
+                    "message": self._reason or httplib.responses[status_code],
                     })
 
     @property
@@ -1090,7 +1096,7 @@ class RequestHandler(object):
                 format = "%d %s: " + e.log_message
                 args = [e.status_code, self._request_summary()] + list(e.args)
                 gen_log.warning(format, *args)
-            if e.status_code not in httplib.responses:
+            if e.status_code not in httplib.responses and not e.reason:
                 gen_log.error("Bad HTTP status code: %d", e.status_code)
                 self.send_error(500, exc_info=sys.exc_info())
             else:
@@ -1478,15 +1484,29 @@ class Application(object):
 
 
 class HTTPError(Exception):
-    """An exception that will turn into an HTTP error response."""
-    def __init__(self, status_code, log_message=None, *args):
+    """An exception that will turn into an HTTP error response.
+
+    :arg int status_code: HTTP status code.  Must be listed in
+        `httplib.responses` unless the ``reason`` keyword argument is given.
+    :arg string log_message: Message to be written to the log for this error
+        (will not be shown to the user unless the `Application` is in debug
+        mode).  May contain ``%s``-style placeholders, which will be filled
+        in with remaining positional parameters.
+    :arg string reason: Keyword-only argument.  The HTTP "reason" phrase
+        to pass in the status line along with ``status_code``.  Normally
+        determined automatically from ``status_code``, but can be used
+        to use a non-standard numeric code.
+    """
+    def __init__(self, status_code, log_message=None, *args, **kwargs):
         self.status_code = status_code
         self.log_message = log_message
         self.args = args
+        self.reason = kwargs.get('reason', None)
 
     def __str__(self):
         message = "HTTP %d: %s" % (
-            self.status_code, httplib.responses[self.status_code])
+            self.status_code,
+            self.reason or httplib.responses[self.status_code])
         if self.log_message:
             return message + " (" + (self.log_message % self.args) + ")"
         else: