import time
import weakref
+from tornado.concurrent import Future
from tornado.escape import utf8
from tornado import httputil, stack_context
from tornado.ioloop import IOLoop
if self._async_clients().get(self.io_loop) is self:
del self._async_clients()[self.io_loop]
- def fetch(self, request, callback, **kwargs):
+ def fetch(self, request, callback=None, **kwargs):
"""Executes a request, calling callback with an `HTTPResponse`.
The request may be either a string URL or an `HTTPRequest` object.
# where normal dicts get converted to HTTPHeaders objects.
request.headers = httputil.HTTPHeaders(request.headers)
request = _RequestProxy(request, self.defaults)
- self.fetch_impl(request, callback)
+ future = Future()
+ if callback is not None:
+ callback = stack_context.wrap(callback)
+ def handle_future(future):
+ exc = future.exception()
+ if isinstance(exc, HTTPError) and exc.response is not None:
+ response = exc.response
+ elif exc is not None:
+ response = HTTPResponse(
+ request, 599, error=exc,
+ request_time=time.time() - request.start_time)
+ else:
+ response = future.result()
+ self.io_loop.add_callback(callback, response)
+ future.add_done_callback(handle_future)
+ def handle_response(response):
+ if response.error:
+ future.set_exception(response.error)
+ else:
+ future.set_result(response)
+ self.fetch_impl(request, handle_response)
+ return future
def fetch_impl(self, request, callback):
raise NotImplementedError()
import sys
from tornado.escape import utf8
-from tornado.httpclient import HTTPRequest, HTTPResponse, _RequestProxy
+from tornado.httpclient import HTTPRequest, HTTPResponse, _RequestProxy, HTTPError
from tornado.iostream import IOStream
from tornado import netutil
from tornado.stack_context import ExceptionStackContext, NullContext
-from tornado.testing import AsyncHTTPTestCase, bind_unused_port
+from tornado.testing import AsyncHTTPTestCase, bind_unused_port, gen_test
from tornado.test.util import unittest
from tornado.util import u, bytes_type
from tornado.web import Application, RequestHandler, url
self.wait()
self.assertEqual(exc_info[0][0], ZeroDivisionError)
+ @gen_test
+ def test_future_interface(self):
+ response = yield self.http_client.fetch(self.get_url('/hello'))
+ self.assertEqual(response.body, b'Hello world!')
+
+ @gen_test
+ def test_future_http_error(self):
+ try:
+ yield self.http_client.fetch(self.get_url('/notfound'))
+ except HTTPError as e:
+ self.assertEqual(e.code, 404)
+ self.assertEqual(e.response.code, 404)
+
class RequestProxyTest(unittest.TestCase):
def test_request_set(self):