]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
simple_httpclient: Add HTTPError subclasses to bury 599 response code
authorBen Darnell <ben@bendarnell.com>
Sun, 8 Apr 2018 15:55:11 +0000 (11:55 -0400)
committerBen Darnell <ben@bendarnell.com>
Sun, 8 Apr 2018 19:25:21 +0000 (15:25 -0400)
tornado/simple_httpclient.py
tornado/test/simple_httpclient_test.py

index c9d159e433041acc9364c3cc8eca8fd279990f60..7696dd184993c9f350de343ebafe2cfdbd707ece 100644 (file)
@@ -35,6 +35,39 @@ except ImportError:
     ssl = None
 
 
+class HTTPTimeoutError(HTTPError):
+    """Error raised by SimpleAsyncHTTPClient on timeout.
+
+    For historical reasons, this is a subclass of `.HTTPClientError`
+    which simulates a response code of 599.
+
+    .. versionadded:: 5.1
+    """
+    def __init__(self, message):
+        super(HTTPTimeoutError, self).__init__(599, message=message)
+
+    def __str__(self):
+        return self.message
+
+
+class HTTPStreamClosedError(HTTPError):
+    """Error raised by SimpleAsyncHTTPClient when the underlying stream is closed.
+
+    When a more specific exception is available (such as `ConnectionResetError`),
+    it may be raised instead of this one.
+
+    For historical reasons, this is a subclass of `.HTTPClientError`
+    which simulates a response code of 599.
+
+    .. versionadded:: 5.1
+    """
+    def __init__(self, message):
+        super(HTTPStreamClosedError, self).__init__(599, message=message)
+
+    def __str__(self):
+        return self.message
+
+
 class SimpleAsyncHTTPClient(AsyncHTTPClient):
     """Non-blocking HTTP client with no external dependencies.
 
@@ -168,7 +201,7 @@ class SimpleAsyncHTTPClient(AsyncHTTPClient):
 
         error_message = "Timeout {0}".format(info) if info else "Timeout"
         timeout_response = HTTPResponse(
-            request, 599, error=HTTPError(599, error_message),
+            request, 599, error=HTTPTimeoutError(error_message),
             request_time=self.io_loop.time() - request.start_time)
         self.io_loop.add_callback(callback, timeout_response)
         del self.waiting[key]
@@ -261,14 +294,14 @@ class _HTTPConnection(httputil.HTTPMessageDelegate):
     def _on_timeout(self, info=None):
         """Timeout callback of _HTTPConnection instance.
 
-        Raise a timeout HTTPError when a timeout occurs.
+        Raise a `HTTPTimeoutError` when a timeout occurs.
 
         :info string key: More detailed timeout information.
         """
         self._timeout = None
         error_message = "Timeout {0}".format(info) if info else "Timeout"
         if self.final_callback is not None:
-            raise HTTPError(599, error_message)
+            raise HTTPTimeoutError(error_message)
 
     def _remove_timeout(self):
         if self._timeout is not None:
@@ -413,7 +446,7 @@ class _HTTPConnection(httputil.HTTPMessageDelegate):
             self._remove_timeout()
             if isinstance(value, StreamClosedError):
                 if value.real_error is None:
-                    value = HTTPError(599, "Stream closed")
+                    value = HTTPStreamClosedError("Stream closed")
                 else:
                     value = value.real_error
             self._run_callback(HTTPResponse(self.request, 599, error=value,
@@ -439,8 +472,8 @@ class _HTTPConnection(httputil.HTTPMessageDelegate):
             if self.stream.error:
                 raise self.stream.error
             try:
-                raise HTTPError(599, message)
-            except HTTPError:
+                raise HTTPStreamClosedError(message)
+            except HTTPStreamClosedError:
                 self._handle_exception(*sys.exc_info())
 
     def headers_received(self, first_line, headers):
index 96fbff0ee24eaa081190ede8116b0ecaf360a2fd..b7daeda9c98c86552d9d9a751ac5b22a05222092 100644 (file)
@@ -13,14 +13,14 @@ import sys
 
 from tornado.escape import to_unicode
 from tornado import gen
-from tornado.httpclient import AsyncHTTPClient, HTTPError
+from tornado.httpclient import AsyncHTTPClient
 from tornado.httputil import HTTPHeaders, ResponseStartLine
 from tornado.ioloop import IOLoop
 from tornado.iostream import UnsatisfiableReadError
 from tornado.log import gen_log
 from tornado.concurrent import Future
 from tornado.netutil import Resolver, bind_sockets
-from tornado.simple_httpclient import SimpleAsyncHTTPClient
+from tornado.simple_httpclient import SimpleAsyncHTTPClient, HTTPStreamClosedError
 from tornado.test.httpclient_test import ChunkHandler, CountdownHandler, HelloWorldHandler, RedirectHandler  # noqa: E501
 from tornado.test import httpclient_test
 from tornado.testing import (AsyncHTTPTestCase, AsyncHTTPSTestCase, AsyncTestCase,
@@ -256,7 +256,7 @@ class SimpleHTTPClientTestMixin(object):
                 self.assertEqual(response.code, 599)
                 self.assertTrue(timeout_min < response.request_time < timeout_max,
                                 response.request_time)
-                self.assertEqual(str(response.error), "HTTP 599: Timeout while connecting")
+                self.assertEqual(str(response.error), "Timeout while connecting")
 
     @skipOnTravis
     def test_request_timeout(self):
@@ -271,7 +271,7 @@ class SimpleHTTPClientTestMixin(object):
             self.assertEqual(response.code, 599)
         self.assertTrue(timeout_min < response.request_time < timeout_max,
                         response.request_time)
-        self.assertEqual(str(response.error), "HTTP 599: Timeout during request")
+        self.assertEqual(str(response.error), "Timeout during request")
         # trigger the hanging request to let it clean up after itself
         self.triggers.popleft()()
 
@@ -365,7 +365,7 @@ class SimpleHTTPClientTestMixin(object):
 
                 self.assertEqual(response.code, 599)
                 self.assertTrue(response.request_time < 1, response.request_time)
-                self.assertEqual(str(response.error), "HTTP 599: Timeout in request queue")
+                self.assertEqual(str(response.error), "Timeout in request queue")
                 self.triggers.popleft()()
                 fut1.add_done_callback(self.stop)
                 self.wait()
@@ -730,7 +730,7 @@ class MaxBodySizeTest(AsyncHTTPTestCase):
 
     def test_large_body(self):
         with ExpectLog(gen_log, "Malformed HTTP message from None: Content-Length too long"):
-            with self.assertRaises(HTTPError):
+            with self.assertRaises(HTTPStreamClosedError):
                 self.fetch('/large', raise_error=True)
 
 
@@ -771,5 +771,5 @@ class ChunkedWithContentLengthTest(AsyncHTTPTestCase):
         # Make sure the invalid headers are detected
         with ExpectLog(gen_log, ("Malformed HTTP message from None: Response "
                                  "with both Transfer-Encoding and Content-Length")):
-            with self.assertRaises(HTTPError):
+            with self.assertRaises(HTTPStreamClosedError):
                 self.fetch('/chunkwithcl', raise_error=True)