def wrapper(*args, **kwargs): future = Future() callback, args, kwargs = replacer.replace(future, args, kwargs) if callback is not None: warnings.warn("callback arguments are deprecated, use the returned Future instead", DeprecationWarning) future.add_done_callback( wrap(functools.partial(_auth_future_to_callback, callback))) def handle_exception(typ, value, tb): if future.done(): return False else: future_set_exc_info(future, (typ, value, tb)) return True with ExceptionStackContext(handle_exception, delay_warning=True): f(*args, **kwargs) return future
def fetch(self, request, callback=None, raise_error=True, **kwargs): """Executes a request, asynchronously returning an `HTTPResponse`. The request may be either a string URL or an `HTTPRequest` object. If it is a string, we construct an `HTTPRequest` using any additional kwargs: ``HTTPRequest(request, **kwargs)`` This method returns a `.Future` whose result is an `HTTPResponse`. By default, the ``Future`` will raise an `HTTPError` if the request returned a non-200 response code (other errors may also be raised if the server could not be contacted). Instead, if ``raise_error`` is set to False, the response will always be returned regardless of the response code. If a ``callback`` is given, it will be invoked with the `HTTPResponse`. In the callback interface, `HTTPError` is not automatically raised. Instead, you must check the response's ``error`` attribute or call its `~HTTPResponse.rethrow` method. .. deprecated:: 5.1 The ``callback`` argument is deprecated and will be removed in 6.0. Use the returned `.Future` instead. The ``raise_error=False`` argument currently suppresses *all* errors, encapsulating them in `HTTPResponse` objects with a 599 response code. This will change in Tornado 6.0: ``raise_error=False`` will only affect the `HTTPError` raised when a non-200 response code is used. """ if self._closed: raise RuntimeError("fetch() called on closed AsyncHTTPClient") if not isinstance(request, HTTPRequest): request = HTTPRequest(url=request, **kwargs) else: if kwargs: raise ValueError("kwargs can't be used if request is an HTTPRequest object") # We may modify this (to add Host, Accept-Encoding, etc), # so make sure we don't modify the caller's object. This is also # where normal dicts get converted to HTTPHeaders objects. request.headers = httputil.HTTPHeaders(request.headers) request = _RequestProxy(request, self.defaults) future = Future() if callback is not None: warnings.warn("callback arguments are deprecated, use the returned Future instead", DeprecationWarning) 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 raise_error and response.error: if isinstance(response.error, HTTPError): response.error.response = response future.set_exception(response.error) else: if response.error and not response._error_is_response_code: warnings.warn("raise_error=False will allow '%s' to be raised in the future" % response.error, DeprecationWarning) future_set_result_unless_cancelled(future, response) self.fetch_impl(request, handle_response) return future