{
    "file_diffs": [
        {
            "old_file_content": "\"\"\"Blocking and non-blocking HTTP client interfaces.\n\nThis module defines a common interface shared by two implementations,\n``simple_httpclient`` and ``curl_httpclient``.  Applications may either\ninstantiate their chosen implementation class directly or use the\n`AsyncHTTPClient` class from this module, which selects an implementation\nthat can be overridden with the `AsyncHTTPClient.configure` method.\n\nThe default implementation is ``simple_httpclient``, and this is expected\nto be suitable for most users' needs.  However, some applications may wish\nto switch to ``curl_httpclient`` for reasons such as the following:\n\n* ``curl_httpclient`` has some features not found in ``simple_httpclient``,\n  including support for HTTP proxies and the ability to use a specified\n  network interface.\n\n* ``curl_httpclient`` is more likely to be compatible with sites that are\n  not-quite-compliant with the HTTP spec, or sites that use little-exercised\n  features of HTTP.\n\n* ``curl_httpclient`` is faster.\n\n* ``curl_httpclient`` was the default prior to Tornado 2.0.\n\nNote that if you are using ``curl_httpclient``, it is highly recommended that\nyou use a recent version of ``libcurl`` and ``pycurl``.  Currently the minimum\nsupported version is 7.18.2, and the recommended version is 7.21.1 or newer.\n\"\"\"\n\nfrom __future__ import absolute_import, division, print_function, with_statement\n\nimport functools\nimport time\nimport weakref\n\nfrom tornado.concurrent import TracebackFuture\nfrom tornado.escape import utf8\nfrom tornado import httputil, stack_context\nfrom tornado.ioloop import IOLoop\nfrom tornado.util import Configurable\n\n\nclass HTTPClient(object):\n    \"\"\"A blocking HTTP client.\n\n    This interface is provided for convenience and testing; most applications\n    that are running an IOLoop will want to use `AsyncHTTPClient` instead.\n    Typical usage looks like this::\n\n        http_client = httpclient.HTTPClient()\n        try:\n            response = http_client.fetch(\"http://www.google.com/\")\n            print response.body\n        except httpclient.HTTPError as e:\n            print \"Error:\", e\n        http_client.close()\n    \"\"\"\n    def __init__(self, async_client_class=None, **kwargs):\n        self._io_loop = IOLoop()\n        if async_client_class is None:\n            async_client_class = AsyncHTTPClient\n        self._async_client = async_client_class(self._io_loop, **kwargs)\n        self._closed = False\n\n    def __del__(self):\n        self.close()\n\n    def close(self):\n        \"\"\"Closes the HTTPClient, freeing any resources used.\"\"\"\n        if not self._closed:\n            self._async_client.close()\n            self._io_loop.close()\n            self._closed = True\n\n    def fetch(self, request, **kwargs):\n        \"\"\"Executes a request, returning an `HTTPResponse`.\n\n        The request may be either a string URL or an `HTTPRequest` object.\n        If it is a string, we construct an `HTTPRequest` using any additional\n        kwargs: ``HTTPRequest(request, **kwargs)``\n\n        If an error occurs during the fetch, we raise an `HTTPError`.\n        \"\"\"\n        response = self._io_loop.run_sync(functools.partial(\n            self._async_client.fetch, request, **kwargs))\n        response.rethrow()\n        return response\n\n\nclass AsyncHTTPClient(Configurable):\n    \"\"\"An non-blocking HTTP client.\n\n    Example usage::\n\n        def handle_request(response):\n            if response.error:\n                print \"Error:\", response.error\n            else:\n                print response.body\n\n        http_client = AsyncHTTPClient()\n        http_client.fetch(\"http://www.google.com/\", handle_request)\n\n    The constructor for this class is magic in several respects: It\n    actually creates an instance of an implementation-specific\n    subclass, and instances are reused as a kind of pseudo-singleton\n    (one per `.IOLoop`).  The keyword argument ``force_instance=True``\n    can be used to suppress this singleton behavior.  Constructor\n    arguments other than ``io_loop`` and ``force_instance`` are\n    deprecated.  The implementation subclass as well as arguments to\n    its constructor can be set with the static method `configure()`\n    \"\"\"\n    @classmethod\n    def configurable_base(cls):\n        return AsyncHTTPClient\n\n    @classmethod\n    def configurable_default(cls):\n        from tornado.simple_httpclient import SimpleAsyncHTTPClient\n        return SimpleAsyncHTTPClient\n\n    @classmethod\n    def _async_clients(cls):\n        attr_name = '_async_client_dict_' + cls.__name__\n        if not hasattr(cls, attr_name):\n            setattr(cls, attr_name, weakref.WeakKeyDictionary())\n        return getattr(cls, attr_name)\n\n    def __new__(cls, io_loop=None, force_instance=False, **kwargs):\n        io_loop = io_loop or IOLoop.current()\n        if io_loop in cls._async_clients() and not force_instance:\n            return cls._async_clients()[io_loop]\n        instance = super(AsyncHTTPClient, cls).__new__(cls, io_loop=io_loop,\n                                                       **kwargs)\n        if not force_instance:\n            cls._async_clients()[io_loop] = instance\n        return instance\n\n    def initialize(self, io_loop, defaults=None):\n        self.io_loop = io_loop\n        self.defaults = dict(HTTPRequest._DEFAULTS)\n        if defaults is not None:\n            self.defaults.update(defaults)\n\n    def close(self):\n        \"\"\"Destroys this HTTP client, freeing any file descriptors used.\n\n        This method is **not needed in normal use** due to the way\n        that `AsyncHTTPClient` objects are transparently reused.\n        ``close()`` is generally only necessary when either the\n        `.IOLoop` is also being closed, or the ``force_instance=True``\n        argument was used when creating the `AsyncHTTPClient`.\n\n        No other methods may be called on the `AsyncHTTPClient` after\n        ``close()``.\n\n        \"\"\"\n        if self._async_clients().get(self.io_loop) is self:\n            del self._async_clients()[self.io_loop]\n\n    def fetch(self, request, callback=None, **kwargs):\n        \"\"\"Executes a request, asynchronously returning an `HTTPResponse`.\n\n        The request may be either a string URL or an `HTTPRequest` object.\n        If it is a string, we construct an `HTTPRequest` using any additional\n        kwargs: ``HTTPRequest(request, **kwargs)``\n\n        This method returns a `.Future` whose result is an\n        `HTTPResponse`.  The ``Future`` wil raise an `HTTPError` if\n        the request returned a non-200 response code.\n\n        If a ``callback`` is given, it will be invoked with the `HTTPResponse`.\n        In the callback interface, `HTTPError` is not automatically raised.\n        Instead, you must check the response's ``error`` attribute or\n        call its `~HTTPResponse.rethrow` method.\n        \"\"\"\n        if not isinstance(request, HTTPRequest):\n            request = HTTPRequest(url=request, **kwargs)\n        # We may modify this (to add Host, Accept-Encoding, etc),\n        # so make sure we don't modify the caller's object.  This is also\n        # where normal dicts get converted to HTTPHeaders objects.\n        request.headers = httputil.HTTPHeaders(request.headers)\n        request = _RequestProxy(request, self.defaults)\n        future = TracebackFuture()\n        if callback is not None:\n            callback = stack_context.wrap(callback)\n\n            def handle_future(future):\n                exc = future.exception()\n                if isinstance(exc, HTTPError) and exc.response is not None:\n                    response = exc.response\n                elif exc is not None:\n                    response = HTTPResponse(\n                        request, 599, error=exc,\n                        request_time=time.time() - request.start_time)\n                else:\n                    response = future.result()\n                self.io_loop.add_callback(callback, response)\n            future.add_done_callback(handle_future)\n\n        def handle_response(response):\n            if response.error:\n                future.set_exception(response.error)\n            else:\n                future.set_result(response)\n        self.fetch_impl(request, handle_response)\n        return future\n\n    def fetch_impl(self, request, callback):\n        raise NotImplementedError()\n\n    @classmethod\n    def configure(cls, impl, **kwargs):\n        \"\"\"Configures the `AsyncHTTPClient` subclass to use.\n\n        ``AsyncHTTPClient()`` actually creates an instance of a subclass.\n        This method may be called with either a class object or the\n        fully-qualified name of such a class (or ``None`` to use the default,\n        ``SimpleAsyncHTTPClient``)\n\n        If additional keyword arguments are given, they will be passed\n        to the constructor of each subclass instance created.  The\n        keyword argument ``max_clients`` determines the maximum number\n        of simultaneous `~AsyncHTTPClient.fetch()` operations that can\n        execute in parallel on each `.IOLoop`.  Additional arguments\n        may be supported depending on the implementation class in use.\n\n        Example::\n\n           AsyncHTTPClient.configure(\"tornado.curl_httpclient.CurlAsyncHTTPClient\")\n        \"\"\"\n        super(AsyncHTTPClient, cls).configure(impl, **kwargs)\n\n\nclass HTTPRequest(object):\n    \"\"\"HTTP client request object.\"\"\"\n\n    # Default values for HTTPRequest parameters.\n    # Merged with the values on the request object by AsyncHTTPClient\n    # implementations.\n    _DEFAULTS = dict(\n        connect_timeout=20.0,\n        request_timeout=20.0,\n        async_timeout=20.0,\n        follow_redirects=True,\n        max_redirects=5,\n        use_gzip=True,\n        proxy_password='',\n        allow_nonstandard_methods=False,\n        validate_cert=True)\n\n    def __init__(self, url, method=\"GET\", headers=None, body=None,\n                 auth_username=None, auth_password=None, auth_mode=None,\n                 connect_timeout=None, request_timeout=None,\n                 async_timeout=None,\n                 if_modified_since=None, follow_redirects=None,\n                 max_redirects=None, user_agent=None, use_gzip=None,\n                 network_interface=None, streaming_callback=None,\n                 header_callback=None, prepare_curl_callback=None,\n                 proxy_host=None, proxy_port=None, proxy_username=None,\n                 proxy_password=None, allow_nonstandard_methods=None,\n                 validate_cert=None, ca_certs=None,\n                 allow_ipv6=None,\n                 client_key=None, client_cert=None):\n        r\"\"\"All parameters except ``url`` are optional.\n\n        :arg string url: URL to fetch\n        :arg string method: HTTP method, e.g. \"GET\" or \"POST\"\n        :arg headers: Additional HTTP headers to pass on the request\n        :arg body: HTTP body to pass on the request\n        :type headers: `~tornado.httputil.HTTPHeaders` or `dict`\n        :arg string auth_username: Username for HTTP authentication\n        :arg string auth_password: Password for HTTP authentication\n        :arg string auth_mode: Authentication mode; default is \"basic\".\n           Allowed values are implementation-defined; ``curl_httpclient``\n           supports \"basic\" and \"digest\"; ``simple_httpclient`` only supports\n           \"basic\"\n        :arg float connect_timeout: Timeout for initial connection in seconds\n        :arg float request_timeout: Timeout for entire request in seconds\n        :arg if_modified_since: Timestamp for ``If-Modified-Since`` header\n        :type if_modified_since: `datetime` or `float`\n        :arg bool follow_redirects: Should redirects be followed automatically\n           or return the 3xx response?\n        :arg int max_redirects: Limit for ``follow_redirects``\n        :arg string user_agent: String to send as ``User-Agent`` header\n        :arg bool use_gzip: Request gzip encoding from the server\n        :arg string network_interface: Network interface to use for request\n        :arg callable streaming_callback: If set, ``streaming_callback`` will\n           be run with each chunk of data as it is received, and\n           ``HTTPResponse.body`` and ``HTTPResponse.buffer`` will be empty in\n           the final response.\n        :arg callable header_callback: If set, ``header_callback`` will\n           be run with each header line as it is received (including the\n           first line, e.g. ``HTTP/1.0 200 OK\\r\\n``, and a final line\n           containing only ``\\r\\n``.  All lines include the trailing newline\n           characters).  ``HTTPResponse.headers`` will be empty in the final\n           response.  This is most useful in conjunction with\n           ``streaming_callback``, because it's the only way to get access to\n           header data while the request is in progress.\n        :arg callable prepare_curl_callback: If set, will be called with\n           a ``pycurl.Curl`` object to allow the application to make additional\n           ``setopt`` calls.\n        :arg string proxy_host: HTTP proxy hostname.  To use proxies,\n           ``proxy_host`` and ``proxy_port`` must be set; ``proxy_username`` and\n           ``proxy_pass`` are optional.  Proxies are currently only supported\n           with ``curl_httpclient``.\n        :arg int proxy_port: HTTP proxy port\n        :arg string proxy_username: HTTP proxy username\n        :arg string proxy_password: HTTP proxy password\n        :arg bool allow_nonstandard_methods: Allow unknown values for ``method``\n           argument?\n        :arg bool validate_cert: For HTTPS requests, validate the server's\n           certificate?\n        :arg string ca_certs: filename of CA certificates in PEM format,\n           or None to use defaults.  Note that in ``curl_httpclient``, if\n           any request uses a custom ``ca_certs`` file, they all must (they\n           don't have to all use the same ``ca_certs``, but it's not possible\n           to mix requests with ``ca_certs`` and requests that use the defaults.\n        :arg bool allow_ipv6: Use IPv6 when available?  Default is false in\n           ``simple_httpclient`` and true in ``curl_httpclient``\n        :arg string client_key: Filename for client SSL key, if any\n        :arg string client_cert: Filename for client SSL certificate, if any\n\n        .. versionadded:: 3.1\n           The ``auth_mode`` argument.\n        \"\"\"\n        if headers is None:\n            headers = httputil.HTTPHeaders()\n        if if_modified_since:\n            headers[\"If-Modified-Since\"] = httputil.format_timestamp(\n                if_modified_since)\n        self.proxy_host = proxy_host\n        self.proxy_port = proxy_port\n        self.proxy_username = proxy_username\n        self.proxy_password = proxy_password\n        self.url = url\n        self.method = method\n        self.headers = headers\n        self.body = utf8(body)\n        self.auth_username = auth_username\n        self.auth_password = auth_password\n        self.auth_mode = auth_mode\n        self.connect_timeout = connect_timeout\n        self.request_timeout = request_timeout\n        self.async_timeout = async_timeout\n        self.follow_redirects = follow_redirects\n        self.max_redirects = max_redirects\n        self.user_agent = user_agent\n        self.use_gzip = use_gzip\n        self.network_interface = network_interface\n        self.streaming_callback = stack_context.wrap(streaming_callback)\n        self.header_callback = stack_context.wrap(header_callback)\n        self.prepare_curl_callback = stack_context.wrap(prepare_curl_callback)\n        self.allow_nonstandard_methods = allow_nonstandard_methods\n        self.validate_cert = validate_cert\n        self.ca_certs = ca_certs\n        self.allow_ipv6 = allow_ipv6\n        self.client_key = client_key\n        self.client_cert = client_cert\n        self.start_time = time.time()\n\n\nclass HTTPResponse(object):\n    \"\"\"HTTP Response object.\n\n    Attributes:\n\n    * request: HTTPRequest object\n\n    * code: numeric HTTP status code, e.g. 200 or 404\n\n    * reason: human-readable reason phrase describing the status code\n      (with curl_httpclient, this is a default value rather than the\n      server's actual response)\n\n    * headers: `tornado.httputil.HTTPHeaders` object\n\n    * buffer: ``cStringIO`` object for response body\n\n    * body: response body as string (created on demand from ``self.buffer``)\n\n    * error: Exception object, if any\n\n    * request_time: seconds from request start to finish\n\n    * time_info: dictionary of diagnostic timing information from the request.\n      Available data are subject to change, but currently uses timings\n      available from http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html,\n      plus ``queue``, which is the delay (if any) introduced by waiting for\n      a slot under `AsyncHTTPClient`'s ``max_clients`` setting.\n    \"\"\"\n    def __init__(self, request, code, headers=None, buffer=None,\n                 effective_url=None, error=None, request_time=None,\n                 time_info=None, reason=None):\n        if isinstance(request, _RequestProxy):\n            self.request = request.request\n        else:\n            self.request = request\n        self.code = code\n        self.reason = reason or httputil.responses.get(code, \"Unknown\")\n        if headers is not None:\n            self.headers = headers\n        else:\n            self.headers = httputil.HTTPHeaders()\n        self.buffer = buffer\n        self._body = None\n        if effective_url is None:\n            self.effective_url = request.url\n        else:\n            self.effective_url = effective_url\n        if error is None:\n            if self.code < 200 or self.code >= 300:\n                self.error = HTTPError(self.code, response=self)\n            else:\n                self.error = None\n        else:\n            self.error = error\n        self.request_time = request_time\n        self.time_info = time_info or {}\n\n    def _get_body(self):\n        if self.buffer is None:\n            return None\n        elif self._body is None:\n            self._body = self.buffer.getvalue()\n\n        return self._body\n\n    body = property(_get_body)\n\n    def rethrow(self):\n        \"\"\"If there was an error on the request, raise an `HTTPError`.\"\"\"\n        if self.error:\n            raise self.error\n\n    def __repr__(self):\n        args = \",\".join(\"%s=%r\" % i for i in sorted(self.__dict__.items()))\n        return \"%s(%s)\" % (self.__class__.__name__, args)\n\n\nclass HTTPError(Exception):\n    \"\"\"Exception thrown for an unsuccessful HTTP request.\n\n    Attributes:\n\n    * ``code`` - HTTP error integer error code, e.g. 404.  Error code 599 is\n      used when no HTTP response was received, e.g. for a timeout.\n\n    * ``response`` - `HTTPResponse` object, if any.\n\n    Note that if ``follow_redirects`` is False, redirects become HTTPErrors,\n    and you can look at ``error.response.headers['Location']`` to see the\n    destination of the redirect.\n    \"\"\"\n    def __init__(self, code, message=None, response=None):\n        self.code = code\n        message = message or httputil.responses.get(code, \"Unknown\")\n        self.response = response\n        Exception.__init__(self, \"HTTP %d: %s\" % (self.code, message))\n\n\nclass _RequestProxy(object):\n    \"\"\"Combines an object with a dictionary of defaults.\n\n    Used internally by AsyncHTTPClient implementations.\n    \"\"\"\n    def __init__(self, request, defaults):\n        self.request = request\n        self.defaults = defaults\n\n    def __getattr__(self, name):\n        request_attr = getattr(self.request, name)\n        if request_attr is not None:\n            return request_attr\n        elif self.defaults is not None:\n            return self.defaults.get(name, None)\n        else:\n            return None\n\n\ndef main():\n    from tornado.options import define, options, parse_command_line\n    define(\"print_headers\", type=bool, default=False)\n    define(\"print_body\", type=bool, default=True)\n    define(\"follow_redirects\", type=bool, default=True)\n    define(\"validate_cert\", type=bool, default=True)\n    args = parse_command_line()\n    client = HTTPClient()\n    for arg in args:\n        try:\n            response = client.fetch(arg,\n                                    follow_redirects=options.follow_redirects,\n                                    validate_cert=options.validate_cert,\n                                    )\n        except HTTPError as e:\n            if e.response is not None:\n                response = e.response\n            else:\n                raise\n        if options.print_headers:\n            print(response.headers)\n        if options.print_body:\n            print(response.body)\n    client.close()\n\nif __name__ == \"__main__\":\n    main()\n",
            "new_file_content": "\"\"\"Blocking and non-blocking HTTP client interfaces.\n\nThis module defines a common interface shared by two implementations,\n``simple_httpclient`` and ``curl_httpclient``.  Applications may either\ninstantiate their chosen implementation class directly or use the\n`AsyncHTTPClient` class from this module, which selects an implementation\nthat can be overridden with the `AsyncHTTPClient.configure` method.\n\nThe default implementation is ``simple_httpclient``, and this is expected\nto be suitable for most users' needs.  However, some applications may wish\nto switch to ``curl_httpclient`` for reasons such as the following:\n\n* ``curl_httpclient`` has some features not found in ``simple_httpclient``,\n  including support for HTTP proxies and the ability to use a specified\n  network interface.\n\n* ``curl_httpclient`` is more likely to be compatible with sites that are\n  not-quite-compliant with the HTTP spec, or sites that use little-exercised\n  features of HTTP.\n\n* ``curl_httpclient`` is faster.\n\n* ``curl_httpclient`` was the default prior to Tornado 2.0.\n\nNote that if you are using ``curl_httpclient``, it is highly recommended that\nyou use a recent version of ``libcurl`` and ``pycurl``.  Currently the minimum\nsupported version is 7.18.2, and the recommended version is 7.21.1 or newer.\n\"\"\"\n\nfrom __future__ import absolute_import, division, print_function, with_statement\n\nimport functools\nimport time\nimport weakref\n\nfrom tornado.concurrent import TracebackFuture\nfrom tornado.escape import utf8\nfrom tornado import httputil, stack_context\nfrom tornado.ioloop import IOLoop\nfrom tornado.util import Configurable\n\n\nclass HTTPClient(object):\n    \"\"\"A blocking HTTP client.\n\n    This interface is provided for convenience and testing; most applications\n    that are running an IOLoop will want to use `AsyncHTTPClient` instead.\n    Typical usage looks like this::\n\n        http_client = httpclient.HTTPClient()\n        try:\n            response = http_client.fetch(\"http://www.google.com/\")\n            print response.body\n        except httpclient.HTTPError as e:\n            print \"Error:\", e\n        http_client.close()\n    \"\"\"\n    def __init__(self, async_client_class=None, **kwargs):\n        self._io_loop = IOLoop()\n        if async_client_class is None:\n            async_client_class = AsyncHTTPClient\n        self._async_client = async_client_class(self._io_loop, **kwargs)\n        self._closed = False\n\n    def __del__(self):\n        self.close()\n\n    def close(self):\n        \"\"\"Closes the HTTPClient, freeing any resources used.\"\"\"\n        if not self._closed:\n            self._async_client.close()\n            self._io_loop.close()\n            self._closed = True\n\n    def fetch(self, request, **kwargs):\n        \"\"\"Executes a request, returning an `HTTPResponse`.\n\n        The request may be either a string URL or an `HTTPRequest` object.\n        If it is a string, we construct an `HTTPRequest` using any additional\n        kwargs: ``HTTPRequest(request, **kwargs)``\n\n        If an error occurs during the fetch, we raise an `HTTPError`.\n        \"\"\"\n        response = self._io_loop.run_sync(functools.partial(\n            self._async_client.fetch, request, **kwargs))\n        response.rethrow()\n        return response\n\n\nclass AsyncHTTPClient(Configurable):\n    \"\"\"An non-blocking HTTP client.\n\n    Example usage::\n\n        def handle_request(response):\n            if response.error:\n                print \"Error:\", response.error\n            else:\n                print response.body\n\n        http_client = AsyncHTTPClient()\n        http_client.fetch(\"http://www.google.com/\", handle_request)\n\n    The constructor for this class is magic in several respects: It\n    actually creates an instance of an implementation-specific\n    subclass, and instances are reused as a kind of pseudo-singleton\n    (one per `.IOLoop`).  The keyword argument ``force_instance=True``\n    can be used to suppress this singleton behavior.  Constructor\n    arguments other than ``io_loop`` and ``force_instance`` are\n    deprecated.  The implementation subclass as well as arguments to\n    its constructor can be set with the static method `configure()`\n    \"\"\"\n    @classmethod\n    def configurable_base(cls):\n        return AsyncHTTPClient\n\n    @classmethod\n    def configurable_default(cls):\n        from tornado.simple_httpclient import SimpleAsyncHTTPClient\n        return SimpleAsyncHTTPClient\n\n    @classmethod\n    def _async_clients(cls):\n        attr_name = '_async_client_dict_' + cls.__name__\n        if not hasattr(cls, attr_name):\n            setattr(cls, attr_name, weakref.WeakKeyDictionary())\n        return getattr(cls, attr_name)\n\n    def __new__(cls, io_loop=None, force_instance=False, **kwargs):\n        io_loop = io_loop or IOLoop.current()\n        if io_loop in cls._async_clients() and not force_instance:\n            return cls._async_clients()[io_loop]\n        instance = super(AsyncHTTPClient, cls).__new__(cls, io_loop=io_loop,\n                                                       **kwargs)\n        if not force_instance:\n            cls._async_clients()[io_loop] = instance\n        return instance\n\n    def initialize(self, io_loop, defaults=None):\n        self.io_loop = io_loop\n        self.defaults = dict(HTTPRequest._DEFAULTS)\n        if defaults is not None:\n            self.defaults.update(defaults)\n\n    def close(self):\n        \"\"\"Destroys this HTTP client, freeing any file descriptors used.\n\n        This method is **not needed in normal use** due to the way\n        that `AsyncHTTPClient` objects are transparently reused.\n        ``close()`` is generally only necessary when either the\n        `.IOLoop` is also being closed, or the ``force_instance=True``\n        argument was used when creating the `AsyncHTTPClient`.\n\n        No other methods may be called on the `AsyncHTTPClient` after\n        ``close()``.\n\n        \"\"\"\n        if self._async_clients().get(self.io_loop) is self:\n            del self._async_clients()[self.io_loop]\n\n    def fetch(self, request, callback=None, **kwargs):\n        \"\"\"Executes a request, asynchronously returning an `HTTPResponse`.\n\n        The request may be either a string URL or an `HTTPRequest` object.\n        If it is a string, we construct an `HTTPRequest` using any additional\n        kwargs: ``HTTPRequest(request, **kwargs)``\n\n        This method returns a `.Future` whose result is an\n        `HTTPResponse`.  The ``Future`` wil raise an `HTTPError` if\n        the request returned a non-200 response code.\n\n        If a ``callback`` is given, it will be invoked with the `HTTPResponse`.\n        In the callback interface, `HTTPError` is not automatically raised.\n        Instead, you must check the response's ``error`` attribute or\n        call its `~HTTPResponse.rethrow` method.\n        \"\"\"\n        if not isinstance(request, HTTPRequest):\n            request = HTTPRequest(url=request, **kwargs)\n        # We may modify this (to add Host, Accept-Encoding, etc),\n        # so make sure we don't modify the caller's object.  This is also\n        # where normal dicts get converted to HTTPHeaders objects.\n        request.headers = httputil.HTTPHeaders(request.headers)\n        request = _RequestProxy(request, self.defaults)\n        future = TracebackFuture()\n        if callback is not None:\n            callback = stack_context.wrap(callback)\n\n            def handle_future(future):\n                exc = future.exception()\n                if isinstance(exc, HTTPError) and exc.response is not None:\n                    response = exc.response\n                elif exc is not None:\n                    response = HTTPResponse(\n                        request, 599, error=exc,\n                        request_time=time.time() - request.start_time)\n                else:\n                    response = future.result()\n                self.io_loop.add_callback(callback, response)\n            future.add_done_callback(handle_future)\n\n        def handle_response(response):\n            if response.error:\n                future.set_exception(response.error)\n            else:\n                future.set_result(response)\n        self.fetch_impl(request, handle_response)\n        return future\n\n    def fetch_impl(self, request, callback):\n        raise NotImplementedError()\n\n    @classmethod\n    def configure(cls, impl, **kwargs):\n        \"\"\"Configures the `AsyncHTTPClient` subclass to use.\n\n        ``AsyncHTTPClient()`` actually creates an instance of a subclass.\n        This method may be called with either a class object or the\n        fully-qualified name of such a class (or ``None`` to use the default,\n        ``SimpleAsyncHTTPClient``)\n\n        If additional keyword arguments are given, they will be passed\n        to the constructor of each subclass instance created.  The\n        keyword argument ``max_clients`` determines the maximum number\n        of simultaneous `~AsyncHTTPClient.fetch()` operations that can\n        execute in parallel on each `.IOLoop`.  Additional arguments\n        may be supported depending on the implementation class in use.\n\n        Example::\n\n           AsyncHTTPClient.configure(\"tornado.curl_httpclient.CurlAsyncHTTPClient\")\n        \"\"\"\n        super(AsyncHTTPClient, cls).configure(impl, **kwargs)\n\n\nclass HTTPRequest(object):\n    \"\"\"HTTP client request object.\"\"\"\n\n    # Default values for HTTPRequest parameters.\n    # Merged with the values on the request object by AsyncHTTPClient\n    # implementations.\n    _DEFAULTS = dict(\n        connect_timeout=20.0,\n        request_timeout=20.0,\n        follow_redirects=True,\n        max_redirects=5,\n        use_gzip=True,\n        proxy_password='',\n        allow_nonstandard_methods=False,\n        validate_cert=True)\n\n    def __init__(self, url, method=\"GET\", headers=None, body=None,\n                 auth_username=None, auth_password=None, auth_mode=None,\n                 connect_timeout=None, request_timeout=None,\n                 if_modified_since=None, follow_redirects=None,\n                 max_redirects=None, user_agent=None, use_gzip=None,\n                 network_interface=None, streaming_callback=None,\n                 header_callback=None, prepare_curl_callback=None,\n                 proxy_host=None, proxy_port=None, proxy_username=None,\n                 proxy_password=None, allow_nonstandard_methods=None,\n                 validate_cert=None, ca_certs=None,\n                 allow_ipv6=None,\n                 client_key=None, client_cert=None):\n        r\"\"\"All parameters except ``url`` are optional.\n\n        :arg string url: URL to fetch\n        :arg string method: HTTP method, e.g. \"GET\" or \"POST\"\n        :arg headers: Additional HTTP headers to pass on the request\n        :arg body: HTTP body to pass on the request\n        :type headers: `~tornado.httputil.HTTPHeaders` or `dict`\n        :arg string auth_username: Username for HTTP authentication\n        :arg string auth_password: Password for HTTP authentication\n        :arg string auth_mode: Authentication mode; default is \"basic\".\n           Allowed values are implementation-defined; ``curl_httpclient``\n           supports \"basic\" and \"digest\"; ``simple_httpclient`` only supports\n           \"basic\"\n        :arg float connect_timeout: Timeout for initial connection in seconds\n        :arg float request_timeout: Timeout for entire request in seconds\n        :arg if_modified_since: Timestamp for ``If-Modified-Since`` header\n        :type if_modified_since: `datetime` or `float`\n        :arg bool follow_redirects: Should redirects be followed automatically\n           or return the 3xx response?\n        :arg int max_redirects: Limit for ``follow_redirects``\n        :arg string user_agent: String to send as ``User-Agent`` header\n        :arg bool use_gzip: Request gzip encoding from the server\n        :arg string network_interface: Network interface to use for request\n        :arg callable streaming_callback: If set, ``streaming_callback`` will\n           be run with each chunk of data as it is received, and\n           ``HTTPResponse.body`` and ``HTTPResponse.buffer`` will be empty in\n           the final response.\n        :arg callable header_callback: If set, ``header_callback`` will\n           be run with each header line as it is received (including the\n           first line, e.g. ``HTTP/1.0 200 OK\\r\\n``, and a final line\n           containing only ``\\r\\n``.  All lines include the trailing newline\n           characters).  ``HTTPResponse.headers`` will be empty in the final\n           response.  This is most useful in conjunction with\n           ``streaming_callback``, because it's the only way to get access to\n           header data while the request is in progress.\n        :arg callable prepare_curl_callback: If set, will be called with\n           a ``pycurl.Curl`` object to allow the application to make additional\n           ``setopt`` calls.\n        :arg string proxy_host: HTTP proxy hostname.  To use proxies,\n           ``proxy_host`` and ``proxy_port`` must be set; ``proxy_username`` and\n           ``proxy_pass`` are optional.  Proxies are currently only supported\n           with ``curl_httpclient``.\n        :arg int proxy_port: HTTP proxy port\n        :arg string proxy_username: HTTP proxy username\n        :arg string proxy_password: HTTP proxy password\n        :arg bool allow_nonstandard_methods: Allow unknown values for ``method``\n           argument?\n        :arg bool validate_cert: For HTTPS requests, validate the server's\n           certificate?\n        :arg string ca_certs: filename of CA certificates in PEM format,\n           or None to use defaults.  Note that in ``curl_httpclient``, if\n           any request uses a custom ``ca_certs`` file, they all must (they\n           don't have to all use the same ``ca_certs``, but it's not possible\n           to mix requests with ``ca_certs`` and requests that use the defaults.\n        :arg bool allow_ipv6: Use IPv6 when available?  Default is false in\n           ``simple_httpclient`` and true in ``curl_httpclient``\n        :arg string client_key: Filename for client SSL key, if any\n        :arg string client_cert: Filename for client SSL certificate, if any\n\n        .. versionadded:: 3.1\n           The ``auth_mode`` argument.\n        \"\"\"\n        if headers is None:\n            headers = httputil.HTTPHeaders()\n        if if_modified_since:\n            headers[\"If-Modified-Since\"] = httputil.format_timestamp(\n                if_modified_since)\n        self.proxy_host = proxy_host\n        self.proxy_port = proxy_port\n        self.proxy_username = proxy_username\n        self.proxy_password = proxy_password\n        self.url = url\n        self.method = method\n        self.headers = headers\n        self.body = utf8(body)\n        self.auth_username = auth_username\n        self.auth_password = auth_password\n        self.auth_mode = auth_mode\n        self.connect_timeout = connect_timeout\n        self.request_timeout = request_timeout\n        self.follow_redirects = follow_redirects\n        self.max_redirects = max_redirects\n        self.user_agent = user_agent\n        self.use_gzip = use_gzip\n        self.network_interface = network_interface\n        self.streaming_callback = stack_context.wrap(streaming_callback)\n        self.header_callback = stack_context.wrap(header_callback)\n        self.prepare_curl_callback = stack_context.wrap(prepare_curl_callback)\n        self.allow_nonstandard_methods = allow_nonstandard_methods\n        self.validate_cert = validate_cert\n        self.ca_certs = ca_certs\n        self.allow_ipv6 = allow_ipv6\n        self.client_key = client_key\n        self.client_cert = client_cert\n        self.start_time = time.time()\n\n\nclass HTTPResponse(object):\n    \"\"\"HTTP Response object.\n\n    Attributes:\n\n    * request: HTTPRequest object\n\n    * code: numeric HTTP status code, e.g. 200 or 404\n\n    * reason: human-readable reason phrase describing the status code\n      (with curl_httpclient, this is a default value rather than the\n      server's actual response)\n\n    * headers: `tornado.httputil.HTTPHeaders` object\n\n    * buffer: ``cStringIO`` object for response body\n\n    * body: response body as string (created on demand from ``self.buffer``)\n\n    * error: Exception object, if any\n\n    * request_time: seconds from request start to finish\n\n    * time_info: dictionary of diagnostic timing information from the request.\n      Available data are subject to change, but currently uses timings\n      available from http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html,\n      plus ``queue``, which is the delay (if any) introduced by waiting for\n      a slot under `AsyncHTTPClient`'s ``max_clients`` setting.\n    \"\"\"\n    def __init__(self, request, code, headers=None, buffer=None,\n                 effective_url=None, error=None, request_time=None,\n                 time_info=None, reason=None):\n        if isinstance(request, _RequestProxy):\n            self.request = request.request\n        else:\n            self.request = request\n        self.code = code\n        self.reason = reason or httputil.responses.get(code, \"Unknown\")\n        if headers is not None:\n            self.headers = headers\n        else:\n            self.headers = httputil.HTTPHeaders()\n        self.buffer = buffer\n        self._body = None\n        if effective_url is None:\n            self.effective_url = request.url\n        else:\n            self.effective_url = effective_url\n        if error is None:\n            if self.code < 200 or self.code >= 300:\n                self.error = HTTPError(self.code, response=self)\n            else:\n                self.error = None\n        else:\n            self.error = error\n        self.request_time = request_time\n        self.time_info = time_info or {}\n\n    def _get_body(self):\n        if self.buffer is None:\n            return None\n        elif self._body is None:\n            self._body = self.buffer.getvalue()\n\n        return self._body\n\n    body = property(_get_body)\n\n    def rethrow(self):\n        \"\"\"If there was an error on the request, raise an `HTTPError`.\"\"\"\n        if self.error:\n            raise self.error\n\n    def __repr__(self):\n        args = \",\".join(\"%s=%r\" % i for i in sorted(self.__dict__.items()))\n        return \"%s(%s)\" % (self.__class__.__name__, args)\n\n\nclass HTTPError(Exception):\n    \"\"\"Exception thrown for an unsuccessful HTTP request.\n\n    Attributes:\n\n    * ``code`` - HTTP error integer error code, e.g. 404.  Error code 599 is\n      used when no HTTP response was received, e.g. for a timeout.\n\n    * ``response`` - `HTTPResponse` object, if any.\n\n    Note that if ``follow_redirects`` is False, redirects become HTTPErrors,\n    and you can look at ``error.response.headers['Location']`` to see the\n    destination of the redirect.\n    \"\"\"\n    def __init__(self, code, message=None, response=None):\n        self.code = code\n        message = message or httputil.responses.get(code, \"Unknown\")\n        self.response = response\n        Exception.__init__(self, \"HTTP %d: %s\" % (self.code, message))\n\n\nclass _RequestProxy(object):\n    \"\"\"Combines an object with a dictionary of defaults.\n\n    Used internally by AsyncHTTPClient implementations.\n    \"\"\"\n    def __init__(self, request, defaults):\n        self.request = request\n        self.defaults = defaults\n\n    def __getattr__(self, name):\n        request_attr = getattr(self.request, name)\n        if request_attr is not None:\n            return request_attr\n        elif self.defaults is not None:\n            return self.defaults.get(name, None)\n        else:\n            return None\n\n\ndef main():\n    from tornado.options import define, options, parse_command_line\n    define(\"print_headers\", type=bool, default=False)\n    define(\"print_body\", type=bool, default=True)\n    define(\"follow_redirects\", type=bool, default=True)\n    define(\"validate_cert\", type=bool, default=True)\n    args = parse_command_line()\n    client = HTTPClient()\n    for arg in args:\n        try:\n            response = client.fetch(arg,\n                                    follow_redirects=options.follow_redirects,\n                                    validate_cert=options.validate_cert,\n                                    )\n        except HTTPError as e:\n            if e.response is not None:\n                response = e.response\n            else:\n                raise\n        if options.print_headers:\n            print(response.headers)\n        if options.print_body:\n            print(response.body)\n    client.close()\n\nif __name__ == \"__main__\":\n    main()\n",
            "header": {
                "file": {
                    "path": "tornado/httpclient.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "91dc2db8",
                "new_commit_hash": "67675894",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tornado/httpclient.py"
            },
            "plus_file": {
                "path": "b/tornado/httpclient.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 241,
                            "length": 7
                        },
                        "new_range": {
                            "start": 241,
                            "length": 6
                        },
                        "section": "class HTTPRequest(object):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    _DEFAULTS = dict(",
                                "type": "context"
                            },
                            {
                                "content": "        connect_timeout=20.0,",
                                "type": "context"
                            },
                            {
                                "content": "        request_timeout=20.0,",
                                "type": "context"
                            },
                            {
                                "content": "        async_timeout=20.0,",
                                "type": "deleted"
                            },
                            {
                                "content": "        follow_redirects=True,",
                                "type": "context"
                            },
                            {
                                "content": "        max_redirects=5,",
                                "type": "context"
                            },
                            {
                                "content": "        use_gzip=True,",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/httpclient.py",
                            "type": "class",
                            "name": "HTTPRequest",
                            "content": "class HTTPRequest(object):\n    \"\"\"HTTP client request object.\"\"\"\n\n    # Default values for HTTPRequest parameters.\n    # Merged with the values on the request object by AsyncHTTPClient\n    # implementations.\n    _DEFAULTS = dict(\n        connect_timeout=20.0,\n        request_timeout=20.0,\n        async_timeout=20.0,\n        follow_redirects=True,\n        max_redirects=5,\n        use_gzip=True,\n        proxy_password='',\n        allow_nonstandard_methods=False,\n        validate_cert=True)\n\n    def __init__(self, url, method=\"GET\", headers=None, body=None,\n                 auth_username=None, auth_password=None, auth_mode=None,\n                 connect_timeout=None, request_timeout=None,\n                 async_timeout=None,\n                 if_modified_since=None, follow_redirects=None,\n                 max_redirects=None, user_agent=None, use_gzip=None,\n                 network_interface=None, streaming_callback=None,\n                 header_callback=None, prepare_curl_callback=None,\n                 proxy_host=None, proxy_port=None, proxy_username=None,\n                 proxy_password=None, allow_nonstandard_methods=None,\n                 validate_cert=None, ca_certs=None,\n                 allow_ipv6=None,\n                 client_key=None, client_cert=None):\n        r\"\"\"All parameters except ``url`` are optional.\n\n        :arg string url: URL to fetch\n        :arg string method: HTTP method, e.g. \"GET\" or \"POST\"\n        :arg headers: Additional HTTP headers to pass on the request\n        :arg body: HTTP body to pass on the request\n        :type headers: `~tornado.httputil.HTTPHeaders` or `dict`\n        :arg string auth_username: Username for HTTP authentication\n        :arg string auth_password: Password for HTTP authentication\n        :arg string auth_mode: Authentication mode; default is \"basic\".\n           Allowed values are implementation-defined; ``curl_httpclient``\n           supports \"basic\" and \"digest\"; ``simple_httpclient`` only supports\n           \"basic\"\n        :arg float connect_timeout: Timeout for initial connection in seconds\n        :arg float request_timeout: Timeout for entire request in seconds\n        :arg if_modified_since: Timestamp for ``If-Modified-Since`` header\n        :type if_modified_since: `datetime` or `float`\n        :arg bool follow_redirects: Should redirects be followed automatically\n           or return the 3xx response?\n        :arg int max_redirects: Limit for ``follow_redirects``\n        :arg string user_agent: String to send as ``User-Agent`` header\n        :arg bool use_gzip: Request gzip encoding from the server\n        :arg string network_interface: Network interface to use for request\n        :arg callable streaming_callback: If set, ``streaming_callback`` will\n           be run with each chunk of data as it is received, and\n           ``HTTPResponse.body`` and ``HTTPResponse.buffer`` will be empty in\n           the final response.\n        :arg callable header_callback: If set, ``header_callback`` will\n           be run with each header line as it is received (including the\n           first line, e.g. ``HTTP/1.0 200 OK\\r\\n``, and a final line\n           containing only ``\\r\\n``.  All lines include the trailing newline\n           characters).  ``HTTPResponse.headers`` will be empty in the final\n           response.  This is most useful in conjunction with\n           ``streaming_callback``, because it's the only way to get access to\n           header data while the request is in progress.\n        :arg callable prepare_curl_callback: If set, will be called with\n           a ``pycurl.Curl`` object to allow the application to make additional\n           ``setopt`` calls.\n        :arg string proxy_host: HTTP proxy hostname.  To use proxies,\n           ``proxy_host`` and ``proxy_port`` must be set; ``proxy_username`` and\n           ``proxy_pass`` are optional.  Proxies are currently only supported\n           with ``curl_httpclient``.\n        :arg int proxy_port: HTTP proxy port\n        :arg string proxy_username: HTTP proxy username\n        :arg string proxy_password: HTTP proxy password\n        :arg bool allow_nonstandard_methods: Allow unknown values for ``method``\n           argument?\n        :arg bool validate_cert: For HTTPS requests, validate the server's\n           certificate?\n        :arg string ca_certs: filename of CA certificates in PEM format,\n           or None to use defaults.  Note that in ``curl_httpclient``, if\n           any request uses a custom ``ca_certs`` file, they all must (they\n           don't have to all use the same ``ca_certs``, but it's not possible\n           to mix requests with ``ca_certs`` and requests that use the defaults.\n        :arg bool allow_ipv6: Use IPv6 when available?  Default is false in\n           ``simple_httpclient`` and true in ``curl_httpclient``\n        :arg string client_key: Filename for client SSL key, if any\n        :arg string client_cert: Filename for client SSL certificate, if any\n\n        .. versionadded:: 3.1\n           The ``auth_mode`` argument.\n        \"\"\"\n        if headers is None:\n            headers = httputil.HTTPHeaders()\n        if if_modified_since:\n            headers[\"If-Modified-Since\"] = httputil.format_timestamp(\n                if_modified_since)\n        self.proxy_host = proxy_host\n        self.proxy_port = proxy_port\n        self.proxy_username = proxy_username\n        self.proxy_password = proxy_password\n        self.url = url\n        self.method = method\n        self.headers = headers\n        self.body = utf8(body)\n        self.auth_username = auth_username\n        self.auth_password = auth_password\n        self.auth_mode = auth_mode\n        self.connect_timeout = connect_timeout\n        self.request_timeout = request_timeout\n        self.async_timeout = async_timeout\n        self.follow_redirects = follow_redirects\n        self.max_redirects = max_redirects\n        self.user_agent = user_agent\n        self.use_gzip = use_gzip\n        self.network_interface = network_interface\n        self.streaming_callback = stack_context.wrap(streaming_callback)\n        self.header_callback = stack_context.wrap(header_callback)\n        self.prepare_curl_callback = stack_context.wrap(prepare_curl_callback)\n        self.allow_nonstandard_methods = allow_nonstandard_methods\n        self.validate_cert = validate_cert\n        self.ca_certs = ca_certs\n        self.allow_ipv6 = allow_ipv6\n        self.client_key = client_key\n        self.client_cert = client_cert\n        self.start_time = time.time()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 235,
                            "end_lineno": 360,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 252,
                            "length": 7
                        },
                        "new_range": {
                            "start": 251,
                            "length": 6
                        },
                        "section": "class HTTPRequest(object):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    def __init__(self, url, method=\"GET\", headers=None, body=None,",
                                "type": "context"
                            },
                            {
                                "content": "                 auth_username=None, auth_password=None, auth_mode=None,",
                                "type": "context"
                            },
                            {
                                "content": "                 connect_timeout=None, request_timeout=None,",
                                "type": "context"
                            },
                            {
                                "content": "                 async_timeout=None,",
                                "type": "deleted"
                            },
                            {
                                "content": "                 if_modified_since=None, follow_redirects=None,",
                                "type": "context"
                            },
                            {
                                "content": "                 max_redirects=None, user_agent=None, use_gzip=None,",
                                "type": "context"
                            },
                            {
                                "content": "                 network_interface=None, streaming_callback=None,",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/httpclient.py",
                            "type": "class",
                            "name": "HTTPRequest",
                            "content": "class HTTPRequest(object):\n    \"\"\"HTTP client request object.\"\"\"\n\n    # Default values for HTTPRequest parameters.\n    # Merged with the values on the request object by AsyncHTTPClient\n    # implementations.\n    _DEFAULTS = dict(\n        connect_timeout=20.0,\n        request_timeout=20.0,\n        async_timeout=20.0,\n        follow_redirects=True,\n        max_redirects=5,\n        use_gzip=True,\n        proxy_password='',\n        allow_nonstandard_methods=False,\n        validate_cert=True)\n\n    def __init__(self, url, method=\"GET\", headers=None, body=None,\n                 auth_username=None, auth_password=None, auth_mode=None,\n                 connect_timeout=None, request_timeout=None,\n                 async_timeout=None,\n                 if_modified_since=None, follow_redirects=None,\n                 max_redirects=None, user_agent=None, use_gzip=None,\n                 network_interface=None, streaming_callback=None,\n                 header_callback=None, prepare_curl_callback=None,\n                 proxy_host=None, proxy_port=None, proxy_username=None,\n                 proxy_password=None, allow_nonstandard_methods=None,\n                 validate_cert=None, ca_certs=None,\n                 allow_ipv6=None,\n                 client_key=None, client_cert=None):\n        r\"\"\"All parameters except ``url`` are optional.\n\n        :arg string url: URL to fetch\n        :arg string method: HTTP method, e.g. \"GET\" or \"POST\"\n        :arg headers: Additional HTTP headers to pass on the request\n        :arg body: HTTP body to pass on the request\n        :type headers: `~tornado.httputil.HTTPHeaders` or `dict`\n        :arg string auth_username: Username for HTTP authentication\n        :arg string auth_password: Password for HTTP authentication\n        :arg string auth_mode: Authentication mode; default is \"basic\".\n           Allowed values are implementation-defined; ``curl_httpclient``\n           supports \"basic\" and \"digest\"; ``simple_httpclient`` only supports\n           \"basic\"\n        :arg float connect_timeout: Timeout for initial connection in seconds\n        :arg float request_timeout: Timeout for entire request in seconds\n        :arg if_modified_since: Timestamp for ``If-Modified-Since`` header\n        :type if_modified_since: `datetime` or `float`\n        :arg bool follow_redirects: Should redirects be followed automatically\n           or return the 3xx response?\n        :arg int max_redirects: Limit for ``follow_redirects``\n        :arg string user_agent: String to send as ``User-Agent`` header\n        :arg bool use_gzip: Request gzip encoding from the server\n        :arg string network_interface: Network interface to use for request\n        :arg callable streaming_callback: If set, ``streaming_callback`` will\n           be run with each chunk of data as it is received, and\n           ``HTTPResponse.body`` and ``HTTPResponse.buffer`` will be empty in\n           the final response.\n        :arg callable header_callback: If set, ``header_callback`` will\n           be run with each header line as it is received (including the\n           first line, e.g. ``HTTP/1.0 200 OK\\r\\n``, and a final line\n           containing only ``\\r\\n``.  All lines include the trailing newline\n           characters).  ``HTTPResponse.headers`` will be empty in the final\n           response.  This is most useful in conjunction with\n           ``streaming_callback``, because it's the only way to get access to\n           header data while the request is in progress.\n        :arg callable prepare_curl_callback: If set, will be called with\n           a ``pycurl.Curl`` object to allow the application to make additional\n           ``setopt`` calls.\n        :arg string proxy_host: HTTP proxy hostname.  To use proxies,\n           ``proxy_host`` and ``proxy_port`` must be set; ``proxy_username`` and\n           ``proxy_pass`` are optional.  Proxies are currently only supported\n           with ``curl_httpclient``.\n        :arg int proxy_port: HTTP proxy port\n        :arg string proxy_username: HTTP proxy username\n        :arg string proxy_password: HTTP proxy password\n        :arg bool allow_nonstandard_methods: Allow unknown values for ``method``\n           argument?\n        :arg bool validate_cert: For HTTPS requests, validate the server's\n           certificate?\n        :arg string ca_certs: filename of CA certificates in PEM format,\n           or None to use defaults.  Note that in ``curl_httpclient``, if\n           any request uses a custom ``ca_certs`` file, they all must (they\n           don't have to all use the same ``ca_certs``, but it's not possible\n           to mix requests with ``ca_certs`` and requests that use the defaults.\n        :arg bool allow_ipv6: Use IPv6 when available?  Default is false in\n           ``simple_httpclient`` and true in ``curl_httpclient``\n        :arg string client_key: Filename for client SSL key, if any\n        :arg string client_cert: Filename for client SSL certificate, if any\n\n        .. versionadded:: 3.1\n           The ``auth_mode`` argument.\n        \"\"\"\n        if headers is None:\n            headers = httputil.HTTPHeaders()\n        if if_modified_since:\n            headers[\"If-Modified-Since\"] = httputil.format_timestamp(\n                if_modified_since)\n        self.proxy_host = proxy_host\n        self.proxy_port = proxy_port\n        self.proxy_username = proxy_username\n        self.proxy_password = proxy_password\n        self.url = url\n        self.method = method\n        self.headers = headers\n        self.body = utf8(body)\n        self.auth_username = auth_username\n        self.auth_password = auth_password\n        self.auth_mode = auth_mode\n        self.connect_timeout = connect_timeout\n        self.request_timeout = request_timeout\n        self.async_timeout = async_timeout\n        self.follow_redirects = follow_redirects\n        self.max_redirects = max_redirects\n        self.user_agent = user_agent\n        self.use_gzip = use_gzip\n        self.network_interface = network_interface\n        self.streaming_callback = stack_context.wrap(streaming_callback)\n        self.header_callback = stack_context.wrap(header_callback)\n        self.prepare_curl_callback = stack_context.wrap(prepare_curl_callback)\n        self.allow_nonstandard_methods = allow_nonstandard_methods\n        self.validate_cert = validate_cert\n        self.ca_certs = ca_certs\n        self.allow_ipv6 = allow_ipv6\n        self.client_key = client_key\n        self.client_cert = client_cert\n        self.start_time = time.time()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 235,
                            "end_lineno": 360,
                            "parent": null
                        },
                        {
                            "file_name": "tornado/httpclient.py",
                            "type": "method",
                            "name": "HTTPRequest.__init__",
                            "content": "class HTTPRequest(object):\n    \"\"\"HTTP client request object.\"\"\"\n\n    # Default values for HTTPRequest parameters.\n    # Merged with the values on the request object by AsyncHTTPClient\n    # implementations.\n    _DEFAULTS = dict(\n        connect_timeout=20.0,\n        request_timeout=20.0,\n        async_timeout=20.0,\n        follow_redirects=True,\n        max_redirects=5,\n        use_gzip=True,\n        proxy_password='',\n        allow_nonstandard_methods=False,\n        validate_cert=True)\n\n    def __init__(self, url, method=\"GET\", headers=None, body=None,\n                 auth_username=None, auth_password=None, auth_mode=None,\n                 connect_timeout=None, request_timeout=None,\n                 async_timeout=None,\n                 if_modified_since=None, follow_redirects=None,\n                 max_redirects=None, user_agent=None, use_gzip=None,\n                 network_interface=None, streaming_callback=None,\n                 header_callback=None, prepare_curl_callback=None,\n                 proxy_host=None, proxy_port=None, proxy_username=None,\n                 proxy_password=None, allow_nonstandard_methods=None,\n                 validate_cert=None, ca_certs=None,\n                 allow_ipv6=None,\n                 client_key=None, client_cert=None):\n        r\"\"\"All parameters except ``url`` are optional.\n\n        :arg string url: URL to fetch\n        :arg string method: HTTP method, e.g. \"GET\" or \"POST\"\n        :arg headers: Additional HTTP headers to pass on the request\n        :arg body: HTTP body to pass on the request\n        :type headers: `~tornado.httputil.HTTPHeaders` or `dict`\n        :arg string auth_username: Username for HTTP authentication\n        :arg string auth_password: Password for HTTP authentication\n        :arg string auth_mode: Authentication mode; default is \"basic\".\n           Allowed values are implementation-defined; ``curl_httpclient``\n           supports \"basic\" and \"digest\"; ``simple_httpclient`` only supports\n           \"basic\"\n        :arg float connect_timeout: Timeout for initial connection in seconds\n        :arg float request_timeout: Timeout for entire request in seconds\n        :arg if_modified_since: Timestamp for ``If-Modified-Since`` header\n        :type if_modified_since: `datetime` or `float`\n        :arg bool follow_redirects: Should redirects be followed automatically\n           or return the 3xx response?\n        :arg int max_redirects: Limit for ``follow_redirects``\n        :arg string user_agent: String to send as ``User-Agent`` header\n        :arg bool use_gzip: Request gzip encoding from the server\n        :arg string network_interface: Network interface to use for request\n        :arg callable streaming_callback: If set, ``streaming_callback`` will\n           be run with each chunk of data as it is received, and\n           ``HTTPResponse.body`` and ``HTTPResponse.buffer`` will be empty in\n           the final response.\n        :arg callable header_callback: If set, ``header_callback`` will\n           be run with each header line as it is received (including the\n           first line, e.g. ``HTTP/1.0 200 OK\\r\\n``, and a final line\n           containing only ``\\r\\n``.  All lines include the trailing newline\n           characters).  ``HTTPResponse.headers`` will be empty in the final\n           response.  This is most useful in conjunction with\n           ``streaming_callback``, because it's the only way to get access to\n           header data while the request is in progress.\n        :arg callable prepare_curl_callback: If set, will be called with\n           a ``pycurl.Curl`` object to allow the application to make additional\n           ``setopt`` calls.\n        :arg string proxy_host: HTTP proxy hostname.  To use proxies,\n           ``proxy_host`` and ``proxy_port`` must be set; ``proxy_username`` and\n           ``proxy_pass`` are optional.  Proxies are currently only supported\n           with ``curl_httpclient``.\n        :arg int proxy_port: HTTP proxy port\n        :arg string proxy_username: HTTP proxy username\n        :arg string proxy_password: HTTP proxy password\n        :arg bool allow_nonstandard_methods: Allow unknown values for ``method``\n           argument?\n        :arg bool validate_cert: For HTTPS requests, validate the server's\n           certificate?\n        :arg string ca_certs: filename of CA certificates in PEM format,\n           or None to use defaults.  Note that in ``curl_httpclient``, if\n           any request uses a custom ``ca_certs`` file, they all must (they\n           don't have to all use the same ``ca_certs``, but it's not possible\n           to mix requests with ``ca_certs`` and requests that use the defaults.\n        :arg bool allow_ipv6: Use IPv6 when available?  Default is false in\n           ``simple_httpclient`` and true in ``curl_httpclient``\n        :arg string client_key: Filename for client SSL key, if any\n        :arg string client_cert: Filename for client SSL certificate, if any\n\n        .. versionadded:: 3.1\n           The ``auth_mode`` argument.\n        \"\"\"\n        if headers is None:\n            headers = httputil.HTTPHeaders()\n        if if_modified_since:\n            headers[\"If-Modified-Since\"] = httputil.format_timestamp(\n                if_modified_since)\n        self.proxy_host = proxy_host\n        self.proxy_port = proxy_port\n        self.proxy_username = proxy_username\n        self.proxy_password = proxy_password\n        self.url = url\n        self.method = method\n        self.headers = headers\n        self.body = utf8(body)\n        self.auth_username = auth_username\n        self.auth_password = auth_password\n        self.auth_mode = auth_mode\n        self.connect_timeout = connect_timeout\n        self.request_timeout = request_timeout\n        self.async_timeout = async_timeout\n        self.follow_redirects = follow_redirects\n        self.max_redirects = max_redirects\n        self.user_agent = user_agent\n        self.use_gzip = use_gzip\n        self.network_interface = network_interface\n        self.streaming_callback = stack_context.wrap(streaming_callback)\n        self.header_callback = stack_context.wrap(header_callback)\n        self.prepare_curl_callback = stack_context.wrap(prepare_curl_callback)\n        self.allow_nonstandard_methods = allow_nonstandard_methods\n        self.validate_cert = validate_cert\n        self.ca_certs = ca_certs\n        self.allow_ipv6 = allow_ipv6\n        self.client_key = client_key\n        self.client_cert = client_cert\n        self.start_time = time.time()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 252,
                            "end_lineno": 360,
                            "parent": {
                                "file_name": "tornado/httpclient.py",
                                "type": "class",
                                "name": "HTTPRequest",
                                "content": "class HTTPRequest(object):\n    \"\"\"HTTP client request object.\"\"\"\n\n    # Default values for HTTPRequest parameters.\n    # Merged with the values on the request object by AsyncHTTPClient\n    # implementations.\n    _DEFAULTS = dict(\n        connect_timeout=20.0,\n        request_timeout=20.0,\n        async_timeout=20.0,\n        follow_redirects=True,\n        max_redirects=5,\n        use_gzip=True,\n        proxy_password='',\n        allow_nonstandard_methods=False,\n        validate_cert=True)\n\n    def __init__(self, url, method=\"GET\", headers=None, body=None,\n                 auth_username=None, auth_password=None, auth_mode=None,\n                 connect_timeout=None, request_timeout=None,\n                 async_timeout=None,\n                 if_modified_since=None, follow_redirects=None,\n                 max_redirects=None, user_agent=None, use_gzip=None,\n                 network_interface=None, streaming_callback=None,\n                 header_callback=None, prepare_curl_callback=None,\n                 proxy_host=None, proxy_port=None, proxy_username=None,\n                 proxy_password=None, allow_nonstandard_methods=None,\n                 validate_cert=None, ca_certs=None,\n                 allow_ipv6=None,\n                 client_key=None, client_cert=None):\n        r\"\"\"All parameters except ``url`` are optional.\n\n        :arg string url: URL to fetch\n        :arg string method: HTTP method, e.g. \"GET\" or \"POST\"\n        :arg headers: Additional HTTP headers to pass on the request\n        :arg body: HTTP body to pass on the request\n        :type headers: `~tornado.httputil.HTTPHeaders` or `dict`\n        :arg string auth_username: Username for HTTP authentication\n        :arg string auth_password: Password for HTTP authentication\n        :arg string auth_mode: Authentication mode; default is \"basic\".\n           Allowed values are implementation-defined; ``curl_httpclient``\n           supports \"basic\" and \"digest\"; ``simple_httpclient`` only supports\n           \"basic\"\n        :arg float connect_timeout: Timeout for initial connection in seconds\n        :arg float request_timeout: Timeout for entire request in seconds\n        :arg if_modified_since: Timestamp for ``If-Modified-Since`` header\n        :type if_modified_since: `datetime` or `float`\n        :arg bool follow_redirects: Should redirects be followed automatically\n           or return the 3xx response?\n        :arg int max_redirects: Limit for ``follow_redirects``\n        :arg string user_agent: String to send as ``User-Agent`` header\n        :arg bool use_gzip: Request gzip encoding from the server\n        :arg string network_interface: Network interface to use for request\n        :arg callable streaming_callback: If set, ``streaming_callback`` will\n           be run with each chunk of data as it is received, and\n           ``HTTPResponse.body`` and ``HTTPResponse.buffer`` will be empty in\n           the final response.\n        :arg callable header_callback: If set, ``header_callback`` will\n           be run with each header line as it is received (including the\n           first line, e.g. ``HTTP/1.0 200 OK\\r\\n``, and a final line\n           containing only ``\\r\\n``.  All lines include the trailing newline\n           characters).  ``HTTPResponse.headers`` will be empty in the final\n           response.  This is most useful in conjunction with\n           ``streaming_callback``, because it's the only way to get access to\n           header data while the request is in progress.\n        :arg callable prepare_curl_callback: If set, will be called with\n           a ``pycurl.Curl`` object to allow the application to make additional\n           ``setopt`` calls.\n        :arg string proxy_host: HTTP proxy hostname.  To use proxies,\n           ``proxy_host`` and ``proxy_port`` must be set; ``proxy_username`` and\n           ``proxy_pass`` are optional.  Proxies are currently only supported\n           with ``curl_httpclient``.\n        :arg int proxy_port: HTTP proxy port\n        :arg string proxy_username: HTTP proxy username\n        :arg string proxy_password: HTTP proxy password\n        :arg bool allow_nonstandard_methods: Allow unknown values for ``method``\n           argument?\n        :arg bool validate_cert: For HTTPS requests, validate the server's\n           certificate?\n        :arg string ca_certs: filename of CA certificates in PEM format,\n           or None to use defaults.  Note that in ``curl_httpclient``, if\n           any request uses a custom ``ca_certs`` file, they all must (they\n           don't have to all use the same ``ca_certs``, but it's not possible\n           to mix requests with ``ca_certs`` and requests that use the defaults.\n        :arg bool allow_ipv6: Use IPv6 when available?  Default is false in\n           ``simple_httpclient`` and true in ``curl_httpclient``\n        :arg string client_key: Filename for client SSL key, if any\n        :arg string client_cert: Filename for client SSL certificate, if any\n\n        .. versionadded:: 3.1\n           The ``auth_mode`` argument.\n        \"\"\"\n        if headers is None:\n            headers = httputil.HTTPHeaders()\n        if if_modified_since:\n            headers[\"If-Modified-Since\"] = httputil.format_timestamp(\n                if_modified_since)\n        self.proxy_host = proxy_host\n        self.proxy_port = proxy_port\n        self.proxy_username = proxy_username\n        self.proxy_password = proxy_password\n        self.url = url\n        self.method = method\n        self.headers = headers\n        self.body = utf8(body)\n        self.auth_username = auth_username\n        self.auth_password = auth_password\n        self.auth_mode = auth_mode\n        self.connect_timeout = connect_timeout\n        self.request_timeout = request_timeout\n        self.async_timeout = async_timeout\n        self.follow_redirects = follow_redirects\n        self.max_redirects = max_redirects\n        self.user_agent = user_agent\n        self.use_gzip = use_gzip\n        self.network_interface = network_interface\n        self.streaming_callback = stack_context.wrap(streaming_callback)\n        self.header_callback = stack_context.wrap(header_callback)\n        self.prepare_curl_callback = stack_context.wrap(prepare_curl_callback)\n        self.allow_nonstandard_methods = allow_nonstandard_methods\n        self.validate_cert = validate_cert\n        self.ca_certs = ca_certs\n        self.allow_ipv6 = allow_ipv6\n        self.client_key = client_key\n        self.client_cert = client_cert\n        self.start_time = time.time()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 235,
                                "end_lineno": 360,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 342,
                            "length": 7
                        },
                        "new_range": {
                            "start": 340,
                            "length": 6
                        },
                        "section": "class HTTPRequest(object):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self.auth_mode = auth_mode",
                                "type": "context"
                            },
                            {
                                "content": "        self.connect_timeout = connect_timeout",
                                "type": "context"
                            },
                            {
                                "content": "        self.request_timeout = request_timeout",
                                "type": "context"
                            },
                            {
                                "content": "        self.async_timeout = async_timeout",
                                "type": "deleted"
                            },
                            {
                                "content": "        self.follow_redirects = follow_redirects",
                                "type": "context"
                            },
                            {
                                "content": "        self.max_redirects = max_redirects",
                                "type": "context"
                            },
                            {
                                "content": "        self.user_agent = user_agent",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/httpclient.py",
                            "type": "class",
                            "name": "HTTPRequest",
                            "content": "class HTTPRequest(object):\n    \"\"\"HTTP client request object.\"\"\"\n\n    # Default values for HTTPRequest parameters.\n    # Merged with the values on the request object by AsyncHTTPClient\n    # implementations.\n    _DEFAULTS = dict(\n        connect_timeout=20.0,\n        request_timeout=20.0,\n        async_timeout=20.0,\n        follow_redirects=True,\n        max_redirects=5,\n        use_gzip=True,\n        proxy_password='',\n        allow_nonstandard_methods=False,\n        validate_cert=True)\n\n    def __init__(self, url, method=\"GET\", headers=None, body=None,\n                 auth_username=None, auth_password=None, auth_mode=None,\n                 connect_timeout=None, request_timeout=None,\n                 async_timeout=None,\n                 if_modified_since=None, follow_redirects=None,\n                 max_redirects=None, user_agent=None, use_gzip=None,\n                 network_interface=None, streaming_callback=None,\n                 header_callback=None, prepare_curl_callback=None,\n                 proxy_host=None, proxy_port=None, proxy_username=None,\n                 proxy_password=None, allow_nonstandard_methods=None,\n                 validate_cert=None, ca_certs=None,\n                 allow_ipv6=None,\n                 client_key=None, client_cert=None):\n        r\"\"\"All parameters except ``url`` are optional.\n\n        :arg string url: URL to fetch\n        :arg string method: HTTP method, e.g. \"GET\" or \"POST\"\n        :arg headers: Additional HTTP headers to pass on the request\n        :arg body: HTTP body to pass on the request\n        :type headers: `~tornado.httputil.HTTPHeaders` or `dict`\n        :arg string auth_username: Username for HTTP authentication\n        :arg string auth_password: Password for HTTP authentication\n        :arg string auth_mode: Authentication mode; default is \"basic\".\n           Allowed values are implementation-defined; ``curl_httpclient``\n           supports \"basic\" and \"digest\"; ``simple_httpclient`` only supports\n           \"basic\"\n        :arg float connect_timeout: Timeout for initial connection in seconds\n        :arg float request_timeout: Timeout for entire request in seconds\n        :arg if_modified_since: Timestamp for ``If-Modified-Since`` header\n        :type if_modified_since: `datetime` or `float`\n        :arg bool follow_redirects: Should redirects be followed automatically\n           or return the 3xx response?\n        :arg int max_redirects: Limit for ``follow_redirects``\n        :arg string user_agent: String to send as ``User-Agent`` header\n        :arg bool use_gzip: Request gzip encoding from the server\n        :arg string network_interface: Network interface to use for request\n        :arg callable streaming_callback: If set, ``streaming_callback`` will\n           be run with each chunk of data as it is received, and\n           ``HTTPResponse.body`` and ``HTTPResponse.buffer`` will be empty in\n           the final response.\n        :arg callable header_callback: If set, ``header_callback`` will\n           be run with each header line as it is received (including the\n           first line, e.g. ``HTTP/1.0 200 OK\\r\\n``, and a final line\n           containing only ``\\r\\n``.  All lines include the trailing newline\n           characters).  ``HTTPResponse.headers`` will be empty in the final\n           response.  This is most useful in conjunction with\n           ``streaming_callback``, because it's the only way to get access to\n           header data while the request is in progress.\n        :arg callable prepare_curl_callback: If set, will be called with\n           a ``pycurl.Curl`` object to allow the application to make additional\n           ``setopt`` calls.\n        :arg string proxy_host: HTTP proxy hostname.  To use proxies,\n           ``proxy_host`` and ``proxy_port`` must be set; ``proxy_username`` and\n           ``proxy_pass`` are optional.  Proxies are currently only supported\n           with ``curl_httpclient``.\n        :arg int proxy_port: HTTP proxy port\n        :arg string proxy_username: HTTP proxy username\n        :arg string proxy_password: HTTP proxy password\n        :arg bool allow_nonstandard_methods: Allow unknown values for ``method``\n           argument?\n        :arg bool validate_cert: For HTTPS requests, validate the server's\n           certificate?\n        :arg string ca_certs: filename of CA certificates in PEM format,\n           or None to use defaults.  Note that in ``curl_httpclient``, if\n           any request uses a custom ``ca_certs`` file, they all must (they\n           don't have to all use the same ``ca_certs``, but it's not possible\n           to mix requests with ``ca_certs`` and requests that use the defaults.\n        :arg bool allow_ipv6: Use IPv6 when available?  Default is false in\n           ``simple_httpclient`` and true in ``curl_httpclient``\n        :arg string client_key: Filename for client SSL key, if any\n        :arg string client_cert: Filename for client SSL certificate, if any\n\n        .. versionadded:: 3.1\n           The ``auth_mode`` argument.\n        \"\"\"\n        if headers is None:\n            headers = httputil.HTTPHeaders()\n        if if_modified_since:\n            headers[\"If-Modified-Since\"] = httputil.format_timestamp(\n                if_modified_since)\n        self.proxy_host = proxy_host\n        self.proxy_port = proxy_port\n        self.proxy_username = proxy_username\n        self.proxy_password = proxy_password\n        self.url = url\n        self.method = method\n        self.headers = headers\n        self.body = utf8(body)\n        self.auth_username = auth_username\n        self.auth_password = auth_password\n        self.auth_mode = auth_mode\n        self.connect_timeout = connect_timeout\n        self.request_timeout = request_timeout\n        self.async_timeout = async_timeout\n        self.follow_redirects = follow_redirects\n        self.max_redirects = max_redirects\n        self.user_agent = user_agent\n        self.use_gzip = use_gzip\n        self.network_interface = network_interface\n        self.streaming_callback = stack_context.wrap(streaming_callback)\n        self.header_callback = stack_context.wrap(header_callback)\n        self.prepare_curl_callback = stack_context.wrap(prepare_curl_callback)\n        self.allow_nonstandard_methods = allow_nonstandard_methods\n        self.validate_cert = validate_cert\n        self.ca_certs = ca_certs\n        self.allow_ipv6 = allow_ipv6\n        self.client_key = client_key\n        self.client_cert = client_cert\n        self.start_time = time.time()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 235,
                            "end_lineno": 360,
                            "parent": null
                        },
                        {
                            "file_name": "tornado/httpclient.py",
                            "type": "method",
                            "name": "HTTPRequest.__init__",
                            "content": "class HTTPRequest(object):\n    \"\"\"HTTP client request object.\"\"\"\n\n    # Default values for HTTPRequest parameters.\n    # Merged with the values on the request object by AsyncHTTPClient\n    # implementations.\n    _DEFAULTS = dict(\n        connect_timeout=20.0,\n        request_timeout=20.0,\n        async_timeout=20.0,\n        follow_redirects=True,\n        max_redirects=5,\n        use_gzip=True,\n        proxy_password='',\n        allow_nonstandard_methods=False,\n        validate_cert=True)\n\n    def __init__(self, url, method=\"GET\", headers=None, body=None,\n                 auth_username=None, auth_password=None, auth_mode=None,\n                 connect_timeout=None, request_timeout=None,\n                 async_timeout=None,\n                 if_modified_since=None, follow_redirects=None,\n                 max_redirects=None, user_agent=None, use_gzip=None,\n                 network_interface=None, streaming_callback=None,\n                 header_callback=None, prepare_curl_callback=None,\n                 proxy_host=None, proxy_port=None, proxy_username=None,\n                 proxy_password=None, allow_nonstandard_methods=None,\n                 validate_cert=None, ca_certs=None,\n                 allow_ipv6=None,\n                 client_key=None, client_cert=None):\n        r\"\"\"All parameters except ``url`` are optional.\n\n        :arg string url: URL to fetch\n        :arg string method: HTTP method, e.g. \"GET\" or \"POST\"\n        :arg headers: Additional HTTP headers to pass on the request\n        :arg body: HTTP body to pass on the request\n        :type headers: `~tornado.httputil.HTTPHeaders` or `dict`\n        :arg string auth_username: Username for HTTP authentication\n        :arg string auth_password: Password for HTTP authentication\n        :arg string auth_mode: Authentication mode; default is \"basic\".\n           Allowed values are implementation-defined; ``curl_httpclient``\n           supports \"basic\" and \"digest\"; ``simple_httpclient`` only supports\n           \"basic\"\n        :arg float connect_timeout: Timeout for initial connection in seconds\n        :arg float request_timeout: Timeout for entire request in seconds\n        :arg if_modified_since: Timestamp for ``If-Modified-Since`` header\n        :type if_modified_since: `datetime` or `float`\n        :arg bool follow_redirects: Should redirects be followed automatically\n           or return the 3xx response?\n        :arg int max_redirects: Limit for ``follow_redirects``\n        :arg string user_agent: String to send as ``User-Agent`` header\n        :arg bool use_gzip: Request gzip encoding from the server\n        :arg string network_interface: Network interface to use for request\n        :arg callable streaming_callback: If set, ``streaming_callback`` will\n           be run with each chunk of data as it is received, and\n           ``HTTPResponse.body`` and ``HTTPResponse.buffer`` will be empty in\n           the final response.\n        :arg callable header_callback: If set, ``header_callback`` will\n           be run with each header line as it is received (including the\n           first line, e.g. ``HTTP/1.0 200 OK\\r\\n``, and a final line\n           containing only ``\\r\\n``.  All lines include the trailing newline\n           characters).  ``HTTPResponse.headers`` will be empty in the final\n           response.  This is most useful in conjunction with\n           ``streaming_callback``, because it's the only way to get access to\n           header data while the request is in progress.\n        :arg callable prepare_curl_callback: If set, will be called with\n           a ``pycurl.Curl`` object to allow the application to make additional\n           ``setopt`` calls.\n        :arg string proxy_host: HTTP proxy hostname.  To use proxies,\n           ``proxy_host`` and ``proxy_port`` must be set; ``proxy_username`` and\n           ``proxy_pass`` are optional.  Proxies are currently only supported\n           with ``curl_httpclient``.\n        :arg int proxy_port: HTTP proxy port\n        :arg string proxy_username: HTTP proxy username\n        :arg string proxy_password: HTTP proxy password\n        :arg bool allow_nonstandard_methods: Allow unknown values for ``method``\n           argument?\n        :arg bool validate_cert: For HTTPS requests, validate the server's\n           certificate?\n        :arg string ca_certs: filename of CA certificates in PEM format,\n           or None to use defaults.  Note that in ``curl_httpclient``, if\n           any request uses a custom ``ca_certs`` file, they all must (they\n           don't have to all use the same ``ca_certs``, but it's not possible\n           to mix requests with ``ca_certs`` and requests that use the defaults.\n        :arg bool allow_ipv6: Use IPv6 when available?  Default is false in\n           ``simple_httpclient`` and true in ``curl_httpclient``\n        :arg string client_key: Filename for client SSL key, if any\n        :arg string client_cert: Filename for client SSL certificate, if any\n\n        .. versionadded:: 3.1\n           The ``auth_mode`` argument.\n        \"\"\"\n        if headers is None:\n            headers = httputil.HTTPHeaders()\n        if if_modified_since:\n            headers[\"If-Modified-Since\"] = httputil.format_timestamp(\n                if_modified_since)\n        self.proxy_host = proxy_host\n        self.proxy_port = proxy_port\n        self.proxy_username = proxy_username\n        self.proxy_password = proxy_password\n        self.url = url\n        self.method = method\n        self.headers = headers\n        self.body = utf8(body)\n        self.auth_username = auth_username\n        self.auth_password = auth_password\n        self.auth_mode = auth_mode\n        self.connect_timeout = connect_timeout\n        self.request_timeout = request_timeout\n        self.async_timeout = async_timeout\n        self.follow_redirects = follow_redirects\n        self.max_redirects = max_redirects\n        self.user_agent = user_agent\n        self.use_gzip = use_gzip\n        self.network_interface = network_interface\n        self.streaming_callback = stack_context.wrap(streaming_callback)\n        self.header_callback = stack_context.wrap(header_callback)\n        self.prepare_curl_callback = stack_context.wrap(prepare_curl_callback)\n        self.allow_nonstandard_methods = allow_nonstandard_methods\n        self.validate_cert = validate_cert\n        self.ca_certs = ca_certs\n        self.allow_ipv6 = allow_ipv6\n        self.client_key = client_key\n        self.client_cert = client_cert\n        self.start_time = time.time()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 252,
                            "end_lineno": 360,
                            "parent": {
                                "file_name": "tornado/httpclient.py",
                                "type": "class",
                                "name": "HTTPRequest",
                                "content": "class HTTPRequest(object):\n    \"\"\"HTTP client request object.\"\"\"\n\n    # Default values for HTTPRequest parameters.\n    # Merged with the values on the request object by AsyncHTTPClient\n    # implementations.\n    _DEFAULTS = dict(\n        connect_timeout=20.0,\n        request_timeout=20.0,\n        async_timeout=20.0,\n        follow_redirects=True,\n        max_redirects=5,\n        use_gzip=True,\n        proxy_password='',\n        allow_nonstandard_methods=False,\n        validate_cert=True)\n\n    def __init__(self, url, method=\"GET\", headers=None, body=None,\n                 auth_username=None, auth_password=None, auth_mode=None,\n                 connect_timeout=None, request_timeout=None,\n                 async_timeout=None,\n                 if_modified_since=None, follow_redirects=None,\n                 max_redirects=None, user_agent=None, use_gzip=None,\n                 network_interface=None, streaming_callback=None,\n                 header_callback=None, prepare_curl_callback=None,\n                 proxy_host=None, proxy_port=None, proxy_username=None,\n                 proxy_password=None, allow_nonstandard_methods=None,\n                 validate_cert=None, ca_certs=None,\n                 allow_ipv6=None,\n                 client_key=None, client_cert=None):\n        r\"\"\"All parameters except ``url`` are optional.\n\n        :arg string url: URL to fetch\n        :arg string method: HTTP method, e.g. \"GET\" or \"POST\"\n        :arg headers: Additional HTTP headers to pass on the request\n        :arg body: HTTP body to pass on the request\n        :type headers: `~tornado.httputil.HTTPHeaders` or `dict`\n        :arg string auth_username: Username for HTTP authentication\n        :arg string auth_password: Password for HTTP authentication\n        :arg string auth_mode: Authentication mode; default is \"basic\".\n           Allowed values are implementation-defined; ``curl_httpclient``\n           supports \"basic\" and \"digest\"; ``simple_httpclient`` only supports\n           \"basic\"\n        :arg float connect_timeout: Timeout for initial connection in seconds\n        :arg float request_timeout: Timeout for entire request in seconds\n        :arg if_modified_since: Timestamp for ``If-Modified-Since`` header\n        :type if_modified_since: `datetime` or `float`\n        :arg bool follow_redirects: Should redirects be followed automatically\n           or return the 3xx response?\n        :arg int max_redirects: Limit for ``follow_redirects``\n        :arg string user_agent: String to send as ``User-Agent`` header\n        :arg bool use_gzip: Request gzip encoding from the server\n        :arg string network_interface: Network interface to use for request\n        :arg callable streaming_callback: If set, ``streaming_callback`` will\n           be run with each chunk of data as it is received, and\n           ``HTTPResponse.body`` and ``HTTPResponse.buffer`` will be empty in\n           the final response.\n        :arg callable header_callback: If set, ``header_callback`` will\n           be run with each header line as it is received (including the\n           first line, e.g. ``HTTP/1.0 200 OK\\r\\n``, and a final line\n           containing only ``\\r\\n``.  All lines include the trailing newline\n           characters).  ``HTTPResponse.headers`` will be empty in the final\n           response.  This is most useful in conjunction with\n           ``streaming_callback``, because it's the only way to get access to\n           header data while the request is in progress.\n        :arg callable prepare_curl_callback: If set, will be called with\n           a ``pycurl.Curl`` object to allow the application to make additional\n           ``setopt`` calls.\n        :arg string proxy_host: HTTP proxy hostname.  To use proxies,\n           ``proxy_host`` and ``proxy_port`` must be set; ``proxy_username`` and\n           ``proxy_pass`` are optional.  Proxies are currently only supported\n           with ``curl_httpclient``.\n        :arg int proxy_port: HTTP proxy port\n        :arg string proxy_username: HTTP proxy username\n        :arg string proxy_password: HTTP proxy password\n        :arg bool allow_nonstandard_methods: Allow unknown values for ``method``\n           argument?\n        :arg bool validate_cert: For HTTPS requests, validate the server's\n           certificate?\n        :arg string ca_certs: filename of CA certificates in PEM format,\n           or None to use defaults.  Note that in ``curl_httpclient``, if\n           any request uses a custom ``ca_certs`` file, they all must (they\n           don't have to all use the same ``ca_certs``, but it's not possible\n           to mix requests with ``ca_certs`` and requests that use the defaults.\n        :arg bool allow_ipv6: Use IPv6 when available?  Default is false in\n           ``simple_httpclient`` and true in ``curl_httpclient``\n        :arg string client_key: Filename for client SSL key, if any\n        :arg string client_cert: Filename for client SSL certificate, if any\n\n        .. versionadded:: 3.1\n           The ``auth_mode`` argument.\n        \"\"\"\n        if headers is None:\n            headers = httputil.HTTPHeaders()\n        if if_modified_since:\n            headers[\"If-Modified-Since\"] = httputil.format_timestamp(\n                if_modified_since)\n        self.proxy_host = proxy_host\n        self.proxy_port = proxy_port\n        self.proxy_username = proxy_username\n        self.proxy_password = proxy_password\n        self.url = url\n        self.method = method\n        self.headers = headers\n        self.body = utf8(body)\n        self.auth_username = auth_username\n        self.auth_password = auth_password\n        self.auth_mode = auth_mode\n        self.connect_timeout = connect_timeout\n        self.request_timeout = request_timeout\n        self.async_timeout = async_timeout\n        self.follow_redirects = follow_redirects\n        self.max_redirects = max_redirects\n        self.user_agent = user_agent\n        self.use_gzip = use_gzip\n        self.network_interface = network_interface\n        self.streaming_callback = stack_context.wrap(streaming_callback)\n        self.header_callback = stack_context.wrap(header_callback)\n        self.prepare_curl_callback = stack_context.wrap(prepare_curl_callback)\n        self.allow_nonstandard_methods = allow_nonstandard_methods\n        self.validate_cert = validate_cert\n        self.ca_certs = ca_certs\n        self.allow_ipv6 = allow_ipv6\n        self.client_key = client_key\n        self.client_cert = client_cert\n        self.start_time = time.time()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 235,
                                "end_lineno": 360,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "#!/usr/bin/env python\nfrom __future__ import absolute_import, division, print_function, with_statement\n\nfrom tornado.escape import utf8, _unicode, native_str\nfrom tornado.httpclient import HTTPResponse, HTTPError, AsyncHTTPClient, main, _RequestProxy\nfrom tornado.httputil import HTTPHeaders\nfrom tornado.iostream import IOStream, SSLIOStream\nfrom tornado.netutil import Resolver, OverrideResolver\nfrom tornado.log import gen_log\nfrom tornado import stack_context\nfrom tornado.util import GzipDecompressor\n\nimport base64\nimport collections\nimport copy\nimport functools\nimport os.path\nimport re\nimport socket\nimport ssl\nimport sys\n\ntry:\n    from io import BytesIO  # python 3\nexcept ImportError:\n    from cStringIO import StringIO as BytesIO  # python 2\n\ntry:\n    import urlparse  # py2\nexcept ImportError:\n    import urllib.parse as urlparse  # py3\n\n_DEFAULT_CA_CERTS = os.path.dirname(__file__) + '/ca-certificates.crt'\n\n\nclass SimpleAsyncHTTPClient(AsyncHTTPClient):\n    \"\"\"Non-blocking HTTP client with no external dependencies.\n\n    This class implements an HTTP 1.1 client on top of Tornado's IOStreams.\n    It does not currently implement all applicable parts of the HTTP\n    specification, but it does enough to work with major web service APIs.\n\n    Some features found in the curl-based AsyncHTTPClient are not yet\n    supported.  In particular, proxies are not supported, connections\n    are not reused, and callers cannot select the network interface to be\n    used.\n    \"\"\"\n    def initialize(self, io_loop, max_clients=10,\n                   hostname_mapping=None, max_buffer_size=104857600,\n                   resolver=None, defaults=None):\n        \"\"\"Creates a AsyncHTTPClient.\n\n        Only a single AsyncHTTPClient instance exists per IOLoop\n        in order to provide limitations on the number of pending connections.\n        force_instance=True may be used to suppress this behavior.\n\n        max_clients is the number of concurrent requests that can be\n        in progress.  Note that this arguments are only used when the\n        client is first created, and will be ignored when an existing\n        client is reused.\n\n        hostname_mapping is a dictionary mapping hostnames to IP addresses.\n        It can be used to make local DNS changes when modifying system-wide\n        settings like /etc/hosts is not possible or desirable (e.g. in\n        unittests).\n\n        max_buffer_size is the number of bytes that can be read by IOStream. It\n        defaults to 100mb.\n        \"\"\"\n        super(SimpleAsyncHTTPClient, self).initialize(io_loop,\n                                                      defaults=defaults)\n        self.max_clients = max_clients\n        self.queue = collections.deque()\n        self.active = {}\n        self.waiting = {}\n        self.max_buffer_size = max_buffer_size\n        if resolver:\n            self.resolver = resolver\n            self.own_resolver = False\n        else:\n            self.resolver = Resolver(io_loop=io_loop)\n            self.own_resolver = True\n        if hostname_mapping is not None:\n            self.resolver = OverrideResolver(resolver=self.resolver,\n                                             mapping=hostname_mapping)\n\n    def close(self):\n        super(SimpleAsyncHTTPClient, self).close()\n        if self.own_resolver:\n            self.resolver.close()\n\n    def fetch_impl(self, request, callback):\n        key = object()\n        self.queue.append((key, request, callback))\n        if not len(self.active) < self.max_clients:\n            timeout_handle = self.io_loop.add_timeout(\n                    request.start_time + request.async_timeout,\n                    functools.partial(self._on_timeout, key))\n            self.waiting[key] = (request, callback, timeout_handle)\n        self._process_queue()\n        if self.queue:\n            gen_log.debug(\"max_clients limit reached, request queued. \"\n                          \"%d active, %d queued requests.\" % (\n                              len(self.active), len(self.queue)))\n\n    def _process_queue(self):\n        with stack_context.NullContext():\n            while self.queue and len(self.active) < self.max_clients:\n                key, request, callback = self.queue.popleft()\n                self._remove_timeout(key)\n                self.active[key] = (request, callback)\n                release_callback = functools.partial(self._release_fetch, key)\n                self._handle_request(request, release_callback, callback)\n\n    def _handle_request(self, request, release_callback, final_callback):\n        _HTTPConnection(self.io_loop, self, request, release_callback,\n                        final_callback, self.max_buffer_size, self.resolver)\n\n    def _release_fetch(self, key):\n        del self.active[key]\n        self._process_queue()\n\n    def _remove_timeout(self, key):\n        if key in self.waiting:\n            request, callback, timeout_handle = self.waiting[key]\n            self.io_loop.remove_timeout(timeout_handle)\n            del self.waiting[key]\n\n    def _on_timeout(self, key):\n        request, callback, timeout_handle = self.waiting[key]\n        self.queue.remove((key, request, callback))\n        timeout_response = HTTPResponse(\n                request, 599, error=HTTPError(599, \"Timeout\"),\n                request_time=self.io_loop.time() - request.start_time)\n        self.io_loop.add_callback(callback, timeout_response)\n        del self.waiting[key]\n\n\nclass _HTTPConnection(object):\n    _SUPPORTED_METHODS = set([\"GET\", \"HEAD\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\", \"OPTIONS\"])\n\n    def __init__(self, io_loop, client, request, release_callback,\n                 final_callback, max_buffer_size, resolver):\n        self.start_time = io_loop.time()\n        self.io_loop = io_loop\n        self.client = client\n        self.request = request\n        self.release_callback = release_callback\n        self.final_callback = final_callback\n        self.max_buffer_size = max_buffer_size\n        self.resolver = resolver\n        self.code = None\n        self.headers = None\n        self.chunks = None\n        self._decompressor = None\n        # Timeout handle returned by IOLoop.add_timeout\n        self._timeout = None\n        with stack_context.ExceptionStackContext(self._handle_exception):\n            self.parsed = urlparse.urlsplit(_unicode(self.request.url))\n            if self.parsed.scheme not in (\"http\", \"https\"):\n                raise ValueError(\"Unsupported url scheme: %s\" %\n                                 self.request.url)\n            # urlsplit results have hostname and port results, but they\n            # didn't support ipv6 literals until python 2.7.\n            netloc = self.parsed.netloc\n            if \"@\" in netloc:\n                userpass, _, netloc = netloc.rpartition(\"@\")\n            match = re.match(r'^(.+):(\\d+)$', netloc)\n            if match:\n                host = match.group(1)\n                port = int(match.group(2))\n            else:\n                host = netloc\n                port = 443 if self.parsed.scheme == \"https\" else 80\n            if re.match(r'^\\[.*\\]$', host):\n                # raw ipv6 addresses in urls are enclosed in brackets\n                host = host[1:-1]\n            self.parsed_hostname = host  # save final host for _on_connect\n\n            if request.allow_ipv6:\n                af = socket.AF_UNSPEC\n            else:\n                # We only try the first IP we get from getaddrinfo,\n                # so restrict to ipv4 by default.\n                af = socket.AF_INET\n\n            self.resolver.resolve(host, port, af, callback=self._on_resolve)\n\n    def _on_resolve(self, addrinfo):\n        self.stream = self._create_stream(addrinfo)\n        timeout = min(self.request.connect_timeout, self.request.request_timeout)\n        if timeout:\n            self._timeout = self.io_loop.add_timeout(\n                self.start_time + timeout,\n                stack_context.wrap(self._on_timeout))\n        self.stream.set_close_callback(self._on_close)\n        # ipv6 addresses are broken (in self.parsed.hostname) until\n        # 2.7, here is correctly parsed value calculated in __init__\n        sockaddr = addrinfo[0][1]\n        self.stream.connect(sockaddr, self._on_connect,\n                            server_hostname=self.parsed_hostname)\n\n    def _create_stream(self, addrinfo):\n        af = addrinfo[0][0]\n        if self.parsed.scheme == \"https\":\n            ssl_options = {}\n            if self.request.validate_cert:\n                ssl_options[\"cert_reqs\"] = ssl.CERT_REQUIRED\n            if self.request.ca_certs is not None:\n                ssl_options[\"ca_certs\"] = self.request.ca_certs\n            else:\n                ssl_options[\"ca_certs\"] = _DEFAULT_CA_CERTS\n            if self.request.client_key is not None:\n                ssl_options[\"keyfile\"] = self.request.client_key\n            if self.request.client_cert is not None:\n                ssl_options[\"certfile\"] = self.request.client_cert\n\n            # SSL interoperability is tricky.  We want to disable\n            # SSLv2 for security reasons; it wasn't disabled by default\n            # until openssl 1.0.  The best way to do this is to use\n            # the SSL_OP_NO_SSLv2, but that wasn't exposed to python\n            # until 3.2.  Python 2.7 adds the ciphers argument, which\n            # can also be used to disable SSLv2.  As a last resort\n            # on python 2.6, we set ssl_version to SSLv3.  This is\n            # more narrow than we'd like since it also breaks\n            # compatibility with servers configured for TLSv1 only,\n            # but nearly all servers support SSLv3:\n            # http://blog.ivanristic.com/2011/09/ssl-survey-protocol-support.html\n            if sys.version_info >= (2, 7):\n                ssl_options[\"ciphers\"] = \"DEFAULT:!SSLv2\"\n            else:\n                # This is really only necessary for pre-1.0 versions\n                # of openssl, but python 2.6 doesn't expose version\n                # information.\n                ssl_options[\"ssl_version\"] = ssl.PROTOCOL_SSLv3\n\n            return SSLIOStream(socket.socket(af),\n                               io_loop=self.io_loop,\n                               ssl_options=ssl_options,\n                               max_buffer_size=self.max_buffer_size)\n        else:\n            return IOStream(socket.socket(af),\n                            io_loop=self.io_loop,\n                            max_buffer_size=self.max_buffer_size)\n\n    def _on_timeout(self):\n        self._timeout = None\n        if self.final_callback is not None:\n            raise HTTPError(599, \"Timeout\")\n\n    def _remove_timeout(self):\n        if self._timeout is not None:\n            self.io_loop.remove_timeout(self._timeout)\n            self._timeout = None\n\n    def _on_connect(self):\n        self._remove_timeout()\n        if self.request.request_timeout:\n            self._timeout = self.io_loop.add_timeout(\n                self.start_time + self.request.request_timeout,\n                stack_context.wrap(self._on_timeout))\n        if (self.request.method not in self._SUPPORTED_METHODS and\n                not self.request.allow_nonstandard_methods):\n            raise KeyError(\"unknown method %s\" % self.request.method)\n        for key in ('network_interface',\n                    'proxy_host', 'proxy_port',\n                    'proxy_username', 'proxy_password'):\n            if getattr(self.request, key, None):\n                raise NotImplementedError('%s not supported' % key)\n        if \"Connection\" not in self.request.headers:\n            self.request.headers[\"Connection\"] = \"close\"\n        if \"Host\" not in self.request.headers:\n            if '@' in self.parsed.netloc:\n                self.request.headers[\"Host\"] = self.parsed.netloc.rpartition('@')[-1]\n            else:\n                self.request.headers[\"Host\"] = self.parsed.netloc\n        username, password = None, None\n        if self.parsed.username is not None:\n            username, password = self.parsed.username, self.parsed.password\n        elif self.request.auth_username is not None:\n            username = self.request.auth_username\n            password = self.request.auth_password or ''\n        if username is not None:\n            if self.request.auth_mode not in (None, \"basic\"):\n                raise ValueError(\"unsupported auth_mode %s\",\n                                 self.request.auth_mode)\n            auth = utf8(username) + b\":\" + utf8(password)\n            self.request.headers[\"Authorization\"] = (b\"Basic \" +\n                                                     base64.b64encode(auth))\n        if self.request.user_agent:\n            self.request.headers[\"User-Agent\"] = self.request.user_agent\n        if not self.request.allow_nonstandard_methods:\n            if self.request.method in (\"POST\", \"PATCH\", \"PUT\"):\n                assert self.request.body is not None\n            else:\n                assert self.request.body is None\n        if self.request.body is not None:\n            self.request.headers[\"Content-Length\"] = str(len(\n                self.request.body))\n        if (self.request.method == \"POST\" and\n                \"Content-Type\" not in self.request.headers):\n            self.request.headers[\"Content-Type\"] = \"application/x-www-form-urlencoded\"\n        if self.request.use_gzip:\n            self.request.headers[\"Accept-Encoding\"] = \"gzip\"\n        req_path = ((self.parsed.path or '/') +\n                   (('?' + self.parsed.query) if self.parsed.query else ''))\n        request_lines = [utf8(\"%s %s HTTP/1.1\" % (self.request.method,\n                                                  req_path))]\n        for k, v in self.request.headers.get_all():\n            line = utf8(k) + b\": \" + utf8(v)\n            if b'\\n' in line:\n                raise ValueError('Newline in header: ' + repr(line))\n            request_lines.append(line)\n        request_str = b\"\\r\\n\".join(request_lines) + b\"\\r\\n\\r\\n\"\n        if self.request.body is not None:\n            request_str += self.request.body\n        self.stream.set_nodelay(True)\n        self.stream.write(request_str)\n        self.stream.read_until_regex(b\"\\r?\\n\\r?\\n\", self._on_headers)\n\n    def _release(self):\n        if self.release_callback is not None:\n            release_callback = self.release_callback\n            self.release_callback = None\n            release_callback()\n\n    def _run_callback(self, response):\n        self._release()\n        if self.final_callback is not None:\n            final_callback = self.final_callback\n            self.final_callback = None\n            self.io_loop.add_callback(final_callback, response)\n\n    def _handle_exception(self, typ, value, tb):\n        if self.final_callback:\n            self._remove_timeout()\n            self._run_callback(HTTPResponse(self.request, 599, error=value,\n                                            request_time=self.io_loop.time() - self.start_time,\n                                            ))\n\n            if hasattr(self, \"stream\"):\n                self.stream.close()\n            return True\n        else:\n            # If our callback has already been called, we are probably\n            # catching an exception that is not caused by us but rather\n            # some child of our callback. Rather than drop it on the floor,\n            # pass it along.\n            return False\n\n    def _on_close(self):\n        if self.final_callback is not None:\n            message = \"Connection closed\"\n            if self.stream.error:\n                message = str(self.stream.error)\n            raise HTTPError(599, message)\n\n    def _handle_1xx(self, code):\n        self.stream.read_until_regex(b\"\\r?\\n\\r?\\n\", self._on_headers)\n\n    def _on_headers(self, data):\n        data = native_str(data.decode(\"latin1\"))\n        first_line, _, header_data = data.partition(\"\\n\")\n        match = re.match(\"HTTP/1.[01] ([0-9]+) ([^\\r]*)\", first_line)\n        assert match\n        code = int(match.group(1))\n        self.headers = HTTPHeaders.parse(header_data)\n        if 100 <= code < 200:\n            self._handle_1xx(code)\n            return\n        else:\n            self.code = code\n            self.reason = match.group(2)\n\n        if \"Content-Length\" in self.headers:\n            if \",\" in self.headers[\"Content-Length\"]:\n                # Proxies sometimes cause Content-Length headers to get\n                # duplicated.  If all the values are identical then we can\n                # use them but if they differ it's an error.\n                pieces = re.split(r',\\s*', self.headers[\"Content-Length\"])\n                if any(i != pieces[0] for i in pieces):\n                    raise ValueError(\"Multiple unequal Content-Lengths: %r\" %\n                                     self.headers[\"Content-Length\"])\n                self.headers[\"Content-Length\"] = pieces[0]\n            content_length = int(self.headers[\"Content-Length\"])\n        else:\n            content_length = None\n\n        if self.request.header_callback is not None:\n            # re-attach the newline we split on earlier\n            self.request.header_callback(first_line + _)\n            for k, v in self.headers.get_all():\n                self.request.header_callback(\"%s: %s\\r\\n\" % (k, v))\n            self.request.header_callback('\\r\\n')\n\n        if self.request.method == \"HEAD\" or self.code == 304:\n            # HEAD requests and 304 responses never have content, even\n            # though they may have content-length headers\n            self._on_body(b\"\")\n            return\n        if 100 <= self.code < 200 or self.code == 204:\n            # These response codes never have bodies\n            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3\n            if (\"Transfer-Encoding\" in self.headers or\n                    content_length not in (None, 0)):\n                raise ValueError(\"Response with code %d should not have body\" %\n                                 self.code)\n            self._on_body(b\"\")\n            return\n\n        if (self.request.use_gzip and\n                self.headers.get(\"Content-Encoding\") == \"gzip\"):\n            self._decompressor = GzipDecompressor()\n        if self.headers.get(\"Transfer-Encoding\") == \"chunked\":\n            self.chunks = []\n            self.stream.read_until(b\"\\r\\n\", self._on_chunk_length)\n        elif content_length is not None:\n            self.stream.read_bytes(content_length, self._on_body)\n        else:\n            self.stream.read_until_close(self._on_body)\n\n    def _on_body(self, data):\n        self._remove_timeout()\n        original_request = getattr(self.request, \"original_request\",\n                                   self.request)\n        if (self.request.follow_redirects and\n            self.request.max_redirects > 0 and\n                self.code in (301, 302, 303, 307)):\n            assert isinstance(self.request, _RequestProxy)\n            new_request = copy.copy(self.request.request)\n            new_request.url = urlparse.urljoin(self.request.url,\n                                               self.headers[\"Location\"])\n            new_request.max_redirects = self.request.max_redirects - 1\n            del new_request.headers[\"Host\"]\n            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4\n            # Client SHOULD make a GET request after a 303.\n            # According to the spec, 302 should be followed by the same\n            # method as the original request, but in practice browsers\n            # treat 302 the same as 303, and many servers use 302 for\n            # compatibility with pre-HTTP/1.1 user agents which don't\n            # understand the 303 status.\n            if self.code in (302, 303):\n                new_request.method = \"GET\"\n                new_request.body = None\n                for h in [\"Content-Length\", \"Content-Type\",\n                          \"Content-Encoding\", \"Transfer-Encoding\"]:\n                    try:\n                        del self.request.headers[h]\n                    except KeyError:\n                        pass\n            new_request.original_request = original_request\n            final_callback = self.final_callback\n            self.final_callback = None\n            self._release()\n            self.client.fetch(new_request, final_callback)\n            self._on_end_request()\n            return\n        if self._decompressor:\n            data = (self._decompressor.decompress(data) +\n                    self._decompressor.flush())\n        if self.request.streaming_callback:\n            if self.chunks is None:\n                # if chunks is not None, we already called streaming_callback\n                # in _on_chunk_data\n                self.request.streaming_callback(data)\n            buffer = BytesIO()\n        else:\n            buffer = BytesIO(data)  # TODO: don't require one big string?\n        response = HTTPResponse(original_request,\n                                self.code, reason=self.reason,\n                                headers=self.headers,\n                                request_time=self.io_loop.time() - self.start_time,\n                                buffer=buffer,\n                                effective_url=self.request.url)\n        self._run_callback(response)\n        self._on_end_request()\n\n    def _on_end_request(self):\n        self.stream.close()\n\n    def _on_chunk_length(self, data):\n        # TODO: \"chunk extensions\" http://tools.ietf.org/html/rfc2616#section-3.6.1\n        length = int(data.strip(), 16)\n        if length == 0:\n            if self._decompressor is not None:\n                tail = self._decompressor.flush()\n                if tail:\n                    # I believe the tail will always be empty (i.e.\n                    # decompress will return all it can).  The purpose\n                    # of the flush call is to detect errors such\n                    # as truncated input.  But in case it ever returns\n                    # anything, treat it as an extra chunk\n                    if self.request.streaming_callback is not None:\n                        self.request.streaming_callback(tail)\n                    else:\n                        self.chunks.append(tail)\n                # all the data has been decompressed, so we don't need to\n                # decompress again in _on_body\n                self._decompressor = None\n            self._on_body(b''.join(self.chunks))\n        else:\n            self.stream.read_bytes(length + 2,  # chunk ends with \\r\\n\n                                   self._on_chunk_data)\n\n    def _on_chunk_data(self, data):\n        assert data[-2:] == b\"\\r\\n\"\n        chunk = data[:-2]\n        if self._decompressor:\n            chunk = self._decompressor.decompress(chunk)\n        if self.request.streaming_callback is not None:\n            self.request.streaming_callback(chunk)\n        else:\n            self.chunks.append(chunk)\n        self.stream.read_until(b\"\\r\\n\", self._on_chunk_length)\n\n\nif __name__ == \"__main__\":\n    AsyncHTTPClient.configure(SimpleAsyncHTTPClient)\n    main()\n",
            "new_file_content": "#!/usr/bin/env python\nfrom __future__ import absolute_import, division, print_function, with_statement\n\nfrom tornado.escape import utf8, _unicode, native_str\nfrom tornado.httpclient import HTTPResponse, HTTPError, AsyncHTTPClient, main, _RequestProxy\nfrom tornado.httputil import HTTPHeaders\nfrom tornado.iostream import IOStream, SSLIOStream\nfrom tornado.netutil import Resolver, OverrideResolver\nfrom tornado.log import gen_log\nfrom tornado import stack_context\nfrom tornado.util import GzipDecompressor\n\nimport base64\nimport collections\nimport copy\nimport functools\nimport os.path\nimport re\nimport socket\nimport ssl\nimport sys\n\ntry:\n    from io import BytesIO  # python 3\nexcept ImportError:\n    from cStringIO import StringIO as BytesIO  # python 2\n\ntry:\n    import urlparse  # py2\nexcept ImportError:\n    import urllib.parse as urlparse  # py3\n\n_DEFAULT_CA_CERTS = os.path.dirname(__file__) + '/ca-certificates.crt'\n\n\nclass SimpleAsyncHTTPClient(AsyncHTTPClient):\n    \"\"\"Non-blocking HTTP client with no external dependencies.\n\n    This class implements an HTTP 1.1 client on top of Tornado's IOStreams.\n    It does not currently implement all applicable parts of the HTTP\n    specification, but it does enough to work with major web service APIs.\n\n    Some features found in the curl-based AsyncHTTPClient are not yet\n    supported.  In particular, proxies are not supported, connections\n    are not reused, and callers cannot select the network interface to be\n    used.\n    \"\"\"\n    def initialize(self, io_loop, max_clients=10,\n                   hostname_mapping=None, max_buffer_size=104857600,\n                   resolver=None, defaults=None):\n        \"\"\"Creates a AsyncHTTPClient.\n\n        Only a single AsyncHTTPClient instance exists per IOLoop\n        in order to provide limitations on the number of pending connections.\n        force_instance=True may be used to suppress this behavior.\n\n        max_clients is the number of concurrent requests that can be\n        in progress.  Note that this arguments are only used when the\n        client is first created, and will be ignored when an existing\n        client is reused.\n\n        hostname_mapping is a dictionary mapping hostnames to IP addresses.\n        It can be used to make local DNS changes when modifying system-wide\n        settings like /etc/hosts is not possible or desirable (e.g. in\n        unittests).\n\n        max_buffer_size is the number of bytes that can be read by IOStream. It\n        defaults to 100mb.\n        \"\"\"\n        super(SimpleAsyncHTTPClient, self).initialize(io_loop,\n                                                      defaults=defaults)\n        self.max_clients = max_clients\n        self.queue = collections.deque()\n        self.active = {}\n        self.waiting = {}\n        self.max_buffer_size = max_buffer_size\n        if resolver:\n            self.resolver = resolver\n            self.own_resolver = False\n        else:\n            self.resolver = Resolver(io_loop=io_loop)\n            self.own_resolver = True\n        if hostname_mapping is not None:\n            self.resolver = OverrideResolver(resolver=self.resolver,\n                                             mapping=hostname_mapping)\n\n    def close(self):\n        super(SimpleAsyncHTTPClient, self).close()\n        if self.own_resolver:\n            self.resolver.close()\n\n    def fetch_impl(self, request, callback):\n        key = object()\n        self.queue.append((key, request, callback))\n        if not len(self.active) < self.max_clients:\n            timeout_handle = self.io_loop.add_timeout(\n                    request.start_time + min(request.connect_timeout, request.request_timeout),\n                    functools.partial(self._on_timeout, key))\n            self.waiting[key] = (request, callback, timeout_handle)\n        self._process_queue()\n        if self.queue:\n            gen_log.debug(\"max_clients limit reached, request queued. \"\n                          \"%d active, %d queued requests.\" % (\n                              len(self.active), len(self.queue)))\n\n    def _process_queue(self):\n        with stack_context.NullContext():\n            while self.queue and len(self.active) < self.max_clients:\n                key, request, callback = self.queue.popleft()\n                self._remove_timeout(key)\n                self.active[key] = (request, callback)\n                release_callback = functools.partial(self._release_fetch, key)\n                self._handle_request(request, release_callback, callback)\n\n    def _handle_request(self, request, release_callback, final_callback):\n        _HTTPConnection(self.io_loop, self, request, release_callback,\n                        final_callback, self.max_buffer_size, self.resolver)\n\n    def _release_fetch(self, key):\n        del self.active[key]\n        self._process_queue()\n\n    def _remove_timeout(self, key):\n        if key in self.waiting:\n            request, callback, timeout_handle = self.waiting[key]\n            self.io_loop.remove_timeout(timeout_handle)\n            del self.waiting[key]\n\n    def _on_timeout(self, key):\n        request, callback, timeout_handle = self.waiting[key]\n        self.queue.remove((key, request, callback))\n        timeout_response = HTTPResponse(\n                request, 599, error=HTTPError(599, \"Timeout\"),\n                request_time=self.io_loop.time() - request.start_time)\n        self.io_loop.add_callback(callback, timeout_response)\n        del self.waiting[key]\n\n\nclass _HTTPConnection(object):\n    _SUPPORTED_METHODS = set([\"GET\", \"HEAD\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\", \"OPTIONS\"])\n\n    def __init__(self, io_loop, client, request, release_callback,\n                 final_callback, max_buffer_size, resolver):\n        self.start_time = io_loop.time()\n        self.io_loop = io_loop\n        self.client = client\n        self.request = request\n        self.release_callback = release_callback\n        self.final_callback = final_callback\n        self.max_buffer_size = max_buffer_size\n        self.resolver = resolver\n        self.code = None\n        self.headers = None\n        self.chunks = None\n        self._decompressor = None\n        # Timeout handle returned by IOLoop.add_timeout\n        self._timeout = None\n        with stack_context.ExceptionStackContext(self._handle_exception):\n            self.parsed = urlparse.urlsplit(_unicode(self.request.url))\n            if self.parsed.scheme not in (\"http\", \"https\"):\n                raise ValueError(\"Unsupported url scheme: %s\" %\n                                 self.request.url)\n            # urlsplit results have hostname and port results, but they\n            # didn't support ipv6 literals until python 2.7.\n            netloc = self.parsed.netloc\n            if \"@\" in netloc:\n                userpass, _, netloc = netloc.rpartition(\"@\")\n            match = re.match(r'^(.+):(\\d+)$', netloc)\n            if match:\n                host = match.group(1)\n                port = int(match.group(2))\n            else:\n                host = netloc\n                port = 443 if self.parsed.scheme == \"https\" else 80\n            if re.match(r'^\\[.*\\]$', host):\n                # raw ipv6 addresses in urls are enclosed in brackets\n                host = host[1:-1]\n            self.parsed_hostname = host  # save final host for _on_connect\n\n            if request.allow_ipv6:\n                af = socket.AF_UNSPEC\n            else:\n                # We only try the first IP we get from getaddrinfo,\n                # so restrict to ipv4 by default.\n                af = socket.AF_INET\n\n            self.resolver.resolve(host, port, af, callback=self._on_resolve)\n\n    def _on_resolve(self, addrinfo):\n        self.stream = self._create_stream(addrinfo)\n        timeout = min(self.request.connect_timeout, self.request.request_timeout)\n        if timeout:\n            self._timeout = self.io_loop.add_timeout(\n                self.start_time + timeout,\n                stack_context.wrap(self._on_timeout))\n        self.stream.set_close_callback(self._on_close)\n        # ipv6 addresses are broken (in self.parsed.hostname) until\n        # 2.7, here is correctly parsed value calculated in __init__\n        sockaddr = addrinfo[0][1]\n        self.stream.connect(sockaddr, self._on_connect,\n                            server_hostname=self.parsed_hostname)\n\n    def _create_stream(self, addrinfo):\n        af = addrinfo[0][0]\n        if self.parsed.scheme == \"https\":\n            ssl_options = {}\n            if self.request.validate_cert:\n                ssl_options[\"cert_reqs\"] = ssl.CERT_REQUIRED\n            if self.request.ca_certs is not None:\n                ssl_options[\"ca_certs\"] = self.request.ca_certs\n            else:\n                ssl_options[\"ca_certs\"] = _DEFAULT_CA_CERTS\n            if self.request.client_key is not None:\n                ssl_options[\"keyfile\"] = self.request.client_key\n            if self.request.client_cert is not None:\n                ssl_options[\"certfile\"] = self.request.client_cert\n\n            # SSL interoperability is tricky.  We want to disable\n            # SSLv2 for security reasons; it wasn't disabled by default\n            # until openssl 1.0.  The best way to do this is to use\n            # the SSL_OP_NO_SSLv2, but that wasn't exposed to python\n            # until 3.2.  Python 2.7 adds the ciphers argument, which\n            # can also be used to disable SSLv2.  As a last resort\n            # on python 2.6, we set ssl_version to SSLv3.  This is\n            # more narrow than we'd like since it also breaks\n            # compatibility with servers configured for TLSv1 only,\n            # but nearly all servers support SSLv3:\n            # http://blog.ivanristic.com/2011/09/ssl-survey-protocol-support.html\n            if sys.version_info >= (2, 7):\n                ssl_options[\"ciphers\"] = \"DEFAULT:!SSLv2\"\n            else:\n                # This is really only necessary for pre-1.0 versions\n                # of openssl, but python 2.6 doesn't expose version\n                # information.\n                ssl_options[\"ssl_version\"] = ssl.PROTOCOL_SSLv3\n\n            return SSLIOStream(socket.socket(af),\n                               io_loop=self.io_loop,\n                               ssl_options=ssl_options,\n                               max_buffer_size=self.max_buffer_size)\n        else:\n            return IOStream(socket.socket(af),\n                            io_loop=self.io_loop,\n                            max_buffer_size=self.max_buffer_size)\n\n    def _on_timeout(self):\n        self._timeout = None\n        if self.final_callback is not None:\n            raise HTTPError(599, \"Timeout\")\n\n    def _remove_timeout(self):\n        if self._timeout is not None:\n            self.io_loop.remove_timeout(self._timeout)\n            self._timeout = None\n\n    def _on_connect(self):\n        self._remove_timeout()\n        if self.request.request_timeout:\n            self._timeout = self.io_loop.add_timeout(\n                self.start_time + self.request.request_timeout,\n                stack_context.wrap(self._on_timeout))\n        if (self.request.method not in self._SUPPORTED_METHODS and\n                not self.request.allow_nonstandard_methods):\n            raise KeyError(\"unknown method %s\" % self.request.method)\n        for key in ('network_interface',\n                    'proxy_host', 'proxy_port',\n                    'proxy_username', 'proxy_password'):\n            if getattr(self.request, key, None):\n                raise NotImplementedError('%s not supported' % key)\n        if \"Connection\" not in self.request.headers:\n            self.request.headers[\"Connection\"] = \"close\"\n        if \"Host\" not in self.request.headers:\n            if '@' in self.parsed.netloc:\n                self.request.headers[\"Host\"] = self.parsed.netloc.rpartition('@')[-1]\n            else:\n                self.request.headers[\"Host\"] = self.parsed.netloc\n        username, password = None, None\n        if self.parsed.username is not None:\n            username, password = self.parsed.username, self.parsed.password\n        elif self.request.auth_username is not None:\n            username = self.request.auth_username\n            password = self.request.auth_password or ''\n        if username is not None:\n            if self.request.auth_mode not in (None, \"basic\"):\n                raise ValueError(\"unsupported auth_mode %s\",\n                                 self.request.auth_mode)\n            auth = utf8(username) + b\":\" + utf8(password)\n            self.request.headers[\"Authorization\"] = (b\"Basic \" +\n                                                     base64.b64encode(auth))\n        if self.request.user_agent:\n            self.request.headers[\"User-Agent\"] = self.request.user_agent\n        if not self.request.allow_nonstandard_methods:\n            if self.request.method in (\"POST\", \"PATCH\", \"PUT\"):\n                assert self.request.body is not None\n            else:\n                assert self.request.body is None\n        if self.request.body is not None:\n            self.request.headers[\"Content-Length\"] = str(len(\n                self.request.body))\n        if (self.request.method == \"POST\" and\n                \"Content-Type\" not in self.request.headers):\n            self.request.headers[\"Content-Type\"] = \"application/x-www-form-urlencoded\"\n        if self.request.use_gzip:\n            self.request.headers[\"Accept-Encoding\"] = \"gzip\"\n        req_path = ((self.parsed.path or '/') +\n                   (('?' + self.parsed.query) if self.parsed.query else ''))\n        request_lines = [utf8(\"%s %s HTTP/1.1\" % (self.request.method,\n                                                  req_path))]\n        for k, v in self.request.headers.get_all():\n            line = utf8(k) + b\": \" + utf8(v)\n            if b'\\n' in line:\n                raise ValueError('Newline in header: ' + repr(line))\n            request_lines.append(line)\n        request_str = b\"\\r\\n\".join(request_lines) + b\"\\r\\n\\r\\n\"\n        if self.request.body is not None:\n            request_str += self.request.body\n        self.stream.set_nodelay(True)\n        self.stream.write(request_str)\n        self.stream.read_until_regex(b\"\\r?\\n\\r?\\n\", self._on_headers)\n\n    def _release(self):\n        if self.release_callback is not None:\n            release_callback = self.release_callback\n            self.release_callback = None\n            release_callback()\n\n    def _run_callback(self, response):\n        self._release()\n        if self.final_callback is not None:\n            final_callback = self.final_callback\n            self.final_callback = None\n            self.io_loop.add_callback(final_callback, response)\n\n    def _handle_exception(self, typ, value, tb):\n        if self.final_callback:\n            self._remove_timeout()\n            self._run_callback(HTTPResponse(self.request, 599, error=value,\n                                            request_time=self.io_loop.time() - self.start_time,\n                                            ))\n\n            if hasattr(self, \"stream\"):\n                self.stream.close()\n            return True\n        else:\n            # If our callback has already been called, we are probably\n            # catching an exception that is not caused by us but rather\n            # some child of our callback. Rather than drop it on the floor,\n            # pass it along.\n            return False\n\n    def _on_close(self):\n        if self.final_callback is not None:\n            message = \"Connection closed\"\n            if self.stream.error:\n                message = str(self.stream.error)\n            raise HTTPError(599, message)\n\n    def _handle_1xx(self, code):\n        self.stream.read_until_regex(b\"\\r?\\n\\r?\\n\", self._on_headers)\n\n    def _on_headers(self, data):\n        data = native_str(data.decode(\"latin1\"))\n        first_line, _, header_data = data.partition(\"\\n\")\n        match = re.match(\"HTTP/1.[01] ([0-9]+) ([^\\r]*)\", first_line)\n        assert match\n        code = int(match.group(1))\n        self.headers = HTTPHeaders.parse(header_data)\n        if 100 <= code < 200:\n            self._handle_1xx(code)\n            return\n        else:\n            self.code = code\n            self.reason = match.group(2)\n\n        if \"Content-Length\" in self.headers:\n            if \",\" in self.headers[\"Content-Length\"]:\n                # Proxies sometimes cause Content-Length headers to get\n                # duplicated.  If all the values are identical then we can\n                # use them but if they differ it's an error.\n                pieces = re.split(r',\\s*', self.headers[\"Content-Length\"])\n                if any(i != pieces[0] for i in pieces):\n                    raise ValueError(\"Multiple unequal Content-Lengths: %r\" %\n                                     self.headers[\"Content-Length\"])\n                self.headers[\"Content-Length\"] = pieces[0]\n            content_length = int(self.headers[\"Content-Length\"])\n        else:\n            content_length = None\n\n        if self.request.header_callback is not None:\n            # re-attach the newline we split on earlier\n            self.request.header_callback(first_line + _)\n            for k, v in self.headers.get_all():\n                self.request.header_callback(\"%s: %s\\r\\n\" % (k, v))\n            self.request.header_callback('\\r\\n')\n\n        if self.request.method == \"HEAD\" or self.code == 304:\n            # HEAD requests and 304 responses never have content, even\n            # though they may have content-length headers\n            self._on_body(b\"\")\n            return\n        if 100 <= self.code < 200 or self.code == 204:\n            # These response codes never have bodies\n            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3\n            if (\"Transfer-Encoding\" in self.headers or\n                    content_length not in (None, 0)):\n                raise ValueError(\"Response with code %d should not have body\" %\n                                 self.code)\n            self._on_body(b\"\")\n            return\n\n        if (self.request.use_gzip and\n                self.headers.get(\"Content-Encoding\") == \"gzip\"):\n            self._decompressor = GzipDecompressor()\n        if self.headers.get(\"Transfer-Encoding\") == \"chunked\":\n            self.chunks = []\n            self.stream.read_until(b\"\\r\\n\", self._on_chunk_length)\n        elif content_length is not None:\n            self.stream.read_bytes(content_length, self._on_body)\n        else:\n            self.stream.read_until_close(self._on_body)\n\n    def _on_body(self, data):\n        self._remove_timeout()\n        original_request = getattr(self.request, \"original_request\",\n                                   self.request)\n        if (self.request.follow_redirects and\n            self.request.max_redirects > 0 and\n                self.code in (301, 302, 303, 307)):\n            assert isinstance(self.request, _RequestProxy)\n            new_request = copy.copy(self.request.request)\n            new_request.url = urlparse.urljoin(self.request.url,\n                                               self.headers[\"Location\"])\n            new_request.max_redirects = self.request.max_redirects - 1\n            del new_request.headers[\"Host\"]\n            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4\n            # Client SHOULD make a GET request after a 303.\n            # According to the spec, 302 should be followed by the same\n            # method as the original request, but in practice browsers\n            # treat 302 the same as 303, and many servers use 302 for\n            # compatibility with pre-HTTP/1.1 user agents which don't\n            # understand the 303 status.\n            if self.code in (302, 303):\n                new_request.method = \"GET\"\n                new_request.body = None\n                for h in [\"Content-Length\", \"Content-Type\",\n                          \"Content-Encoding\", \"Transfer-Encoding\"]:\n                    try:\n                        del self.request.headers[h]\n                    except KeyError:\n                        pass\n            new_request.original_request = original_request\n            final_callback = self.final_callback\n            self.final_callback = None\n            self._release()\n            self.client.fetch(new_request, final_callback)\n            self._on_end_request()\n            return\n        if self._decompressor:\n            data = (self._decompressor.decompress(data) +\n                    self._decompressor.flush())\n        if self.request.streaming_callback:\n            if self.chunks is None:\n                # if chunks is not None, we already called streaming_callback\n                # in _on_chunk_data\n                self.request.streaming_callback(data)\n            buffer = BytesIO()\n        else:\n            buffer = BytesIO(data)  # TODO: don't require one big string?\n        response = HTTPResponse(original_request,\n                                self.code, reason=self.reason,\n                                headers=self.headers,\n                                request_time=self.io_loop.time() - self.start_time,\n                                buffer=buffer,\n                                effective_url=self.request.url)\n        self._run_callback(response)\n        self._on_end_request()\n\n    def _on_end_request(self):\n        self.stream.close()\n\n    def _on_chunk_length(self, data):\n        # TODO: \"chunk extensions\" http://tools.ietf.org/html/rfc2616#section-3.6.1\n        length = int(data.strip(), 16)\n        if length == 0:\n            if self._decompressor is not None:\n                tail = self._decompressor.flush()\n                if tail:\n                    # I believe the tail will always be empty (i.e.\n                    # decompress will return all it can).  The purpose\n                    # of the flush call is to detect errors such\n                    # as truncated input.  But in case it ever returns\n                    # anything, treat it as an extra chunk\n                    if self.request.streaming_callback is not None:\n                        self.request.streaming_callback(tail)\n                    else:\n                        self.chunks.append(tail)\n                # all the data has been decompressed, so we don't need to\n                # decompress again in _on_body\n                self._decompressor = None\n            self._on_body(b''.join(self.chunks))\n        else:\n            self.stream.read_bytes(length + 2,  # chunk ends with \\r\\n\n                                   self._on_chunk_data)\n\n    def _on_chunk_data(self, data):\n        assert data[-2:] == b\"\\r\\n\"\n        chunk = data[:-2]\n        if self._decompressor:\n            chunk = self._decompressor.decompress(chunk)\n        if self.request.streaming_callback is not None:\n            self.request.streaming_callback(chunk)\n        else:\n            self.chunks.append(chunk)\n        self.stream.read_until(b\"\\r\\n\", self._on_chunk_length)\n\n\nif __name__ == \"__main__\":\n    AsyncHTTPClient.configure(SimpleAsyncHTTPClient)\n    main()\n",
            "header": {
                "file": {
                    "path": "tornado/simple_httpclient.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "75cb9ff7",
                "new_commit_hash": "eb241122",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tornado/simple_httpclient.py"
            },
            "plus_file": {
                "path": "b/tornado/simple_httpclient.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 94,
                            "length": 7
                        },
                        "new_range": {
                            "start": 94,
                            "length": 7
                        },
                        "section": "class SimpleAsyncHTTPClient(AsyncHTTPClient):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self.queue.append((key, request, callback))",
                                "type": "context"
                            },
                            {
                                "content": "        if not len(self.active) < self.max_clients:",
                                "type": "context"
                            },
                            {
                                "content": "            timeout_handle = self.io_loop.add_timeout(",
                                "type": "context"
                            },
                            {
                                "content": "                    request.start_time + request.async_timeout,",
                                "type": "deleted"
                            },
                            {
                                "content": "                    request.start_time + min(request.connect_timeout, request.request_timeout),",
                                "type": "added"
                            },
                            {
                                "content": "                    functools.partial(self._on_timeout, key))",
                                "type": "context"
                            },
                            {
                                "content": "            self.waiting[key] = (request, callback, timeout_handle)",
                                "type": "context"
                            },
                            {
                                "content": "        self._process_queue()",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/simple_httpclient.py",
                            "type": "method",
                            "name": "SimpleAsyncHTTPClient.fetch_impl",
                            "content": "class SimpleAsyncHTTPClient(AsyncHTTPClient):\n    \"\"\"Non-blocking HTTP client with no external dependencies.\n\n    This class implements an HTTP 1.1 client on top of Tornado's IOStreams.\n    It does not currently implement all applicable parts of the HTTP\n    specification, but it does enough to work with major web service APIs.\n\n    Some features found in the curl-based AsyncHTTPClient are not yet\n    supported.  In particular, proxies are not supported, connections\n    are not reused, and callers cannot select the network interface to be\n    used.\n    \"\"\"\n    def initialize(self, io_loop, max_clients=10,\n                   hostname_mapping=None, max_buffer_size=104857600,\n                   resolver=None, defaults=None):\n        \"\"\"Creates a AsyncHTTPClient.\n\n        Only a single AsyncHTTPClient instance exists per IOLoop\n        in order to provide limitations on the number of pending connections.\n        force_instance=True may be used to suppress this behavior.\n\n        max_clients is the number of concurrent requests that can be\n        in progress.  Note that this arguments are only used when the\n        client is first created, and will be ignored when an existing\n        client is reused.\n\n        hostname_mapping is a dictionary mapping hostnames to IP addresses.\n        It can be used to make local DNS changes when modifying system-wide\n        settings like /etc/hosts is not possible or desirable (e.g. in\n        unittests).\n\n        max_buffer_size is the number of bytes that can be read by IOStream. It\n        defaults to 100mb.\n        \"\"\"\n        super(SimpleAsyncHTTPClient, self).initialize(io_loop,\n                                                      defaults=defaults)\n        self.max_clients = max_clients\n        self.queue = collections.deque()\n        self.active = {}\n        self.waiting = {}\n        self.max_buffer_size = max_buffer_size\n        if resolver:\n            self.resolver = resolver\n            self.own_resolver = False\n        else:\n            self.resolver = Resolver(io_loop=io_loop)\n            self.own_resolver = True\n        if hostname_mapping is not None:\n            self.resolver = OverrideResolver(resolver=self.resolver,\n                                             mapping=hostname_mapping)\n\n    def close(self):\n        super(SimpleAsyncHTTPClient, self).close()\n        if self.own_resolver:\n            self.resolver.close()\n\n    def fetch_impl(self, request, callback):\n        key = object()\n        self.queue.append((key, request, callback))\n        if not len(self.active) < self.max_clients:\n            timeout_handle = self.io_loop.add_timeout(\n                    request.start_time + request.async_timeout,\n                    functools.partial(self._on_timeout, key))\n            self.waiting[key] = (request, callback, timeout_handle)\n        self._process_queue()\n        if self.queue:\n            gen_log.debug(\"max_clients limit reached, request queued. \"\n                          \"%d active, %d queued requests.\" % (\n                              len(self.active), len(self.queue)))\n\n    def _process_queue(self):\n        with stack_context.NullContext():\n            while self.queue and len(self.active) < self.max_clients:\n                key, request, callback = self.queue.popleft()\n                self._remove_timeout(key)\n                self.active[key] = (request, callback)\n                release_callback = functools.partial(self._release_fetch, key)\n                self._handle_request(request, release_callback, callback)\n\n    def _handle_request(self, request, release_callback, final_callback):\n        _HTTPConnection(self.io_loop, self, request, release_callback,\n                        final_callback, self.max_buffer_size, self.resolver)\n\n    def _release_fetch(self, key):\n        del self.active[key]\n        self._process_queue()\n\n    def _remove_timeout(self, key):\n        if key in self.waiting:\n            request, callback, timeout_handle = self.waiting[key]\n            self.io_loop.remove_timeout(timeout_handle)\n            del self.waiting[key]\n\n    def _on_timeout(self, key):\n        request, callback, timeout_handle = self.waiting[key]\n        self.queue.remove((key, request, callback))\n        timeout_response = HTTPResponse(\n                request, 599, error=HTTPError(599, \"Timeout\"),\n                request_time=self.io_loop.time() - request.start_time)\n        self.io_loop.add_callback(callback, timeout_response)\n        del self.waiting[key]",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 92,
                            "end_lineno": 104,
                            "parent": {
                                "file_name": "tornado/simple_httpclient.py",
                                "type": "class",
                                "name": "SimpleAsyncHTTPClient",
                                "content": "class SimpleAsyncHTTPClient(AsyncHTTPClient):\n    \"\"\"Non-blocking HTTP client with no external dependencies.\n\n    This class implements an HTTP 1.1 client on top of Tornado's IOStreams.\n    It does not currently implement all applicable parts of the HTTP\n    specification, but it does enough to work with major web service APIs.\n\n    Some features found in the curl-based AsyncHTTPClient are not yet\n    supported.  In particular, proxies are not supported, connections\n    are not reused, and callers cannot select the network interface to be\n    used.\n    \"\"\"\n    def initialize(self, io_loop, max_clients=10,\n                   hostname_mapping=None, max_buffer_size=104857600,\n                   resolver=None, defaults=None):\n        \"\"\"Creates a AsyncHTTPClient.\n\n        Only a single AsyncHTTPClient instance exists per IOLoop\n        in order to provide limitations on the number of pending connections.\n        force_instance=True may be used to suppress this behavior.\n\n        max_clients is the number of concurrent requests that can be\n        in progress.  Note that this arguments are only used when the\n        client is first created, and will be ignored when an existing\n        client is reused.\n\n        hostname_mapping is a dictionary mapping hostnames to IP addresses.\n        It can be used to make local DNS changes when modifying system-wide\n        settings like /etc/hosts is not possible or desirable (e.g. in\n        unittests).\n\n        max_buffer_size is the number of bytes that can be read by IOStream. It\n        defaults to 100mb.\n        \"\"\"\n        super(SimpleAsyncHTTPClient, self).initialize(io_loop,\n                                                      defaults=defaults)\n        self.max_clients = max_clients\n        self.queue = collections.deque()\n        self.active = {}\n        self.waiting = {}\n        self.max_buffer_size = max_buffer_size\n        if resolver:\n            self.resolver = resolver\n            self.own_resolver = False\n        else:\n            self.resolver = Resolver(io_loop=io_loop)\n            self.own_resolver = True\n        if hostname_mapping is not None:\n            self.resolver = OverrideResolver(resolver=self.resolver,\n                                             mapping=hostname_mapping)\n\n    def close(self):\n        super(SimpleAsyncHTTPClient, self).close()\n        if self.own_resolver:\n            self.resolver.close()\n\n    def fetch_impl(self, request, callback):\n        key = object()\n        self.queue.append((key, request, callback))\n        if not len(self.active) < self.max_clients:\n            timeout_handle = self.io_loop.add_timeout(\n                    request.start_time + request.async_timeout,\n                    functools.partial(self._on_timeout, key))\n            self.waiting[key] = (request, callback, timeout_handle)\n        self._process_queue()\n        if self.queue:\n            gen_log.debug(\"max_clients limit reached, request queued. \"\n                          \"%d active, %d queued requests.\" % (\n                              len(self.active), len(self.queue)))\n\n    def _process_queue(self):\n        with stack_context.NullContext():\n            while self.queue and len(self.active) < self.max_clients:\n                key, request, callback = self.queue.popleft()\n                self._remove_timeout(key)\n                self.active[key] = (request, callback)\n                release_callback = functools.partial(self._release_fetch, key)\n                self._handle_request(request, release_callback, callback)\n\n    def _handle_request(self, request, release_callback, final_callback):\n        _HTTPConnection(self.io_loop, self, request, release_callback,\n                        final_callback, self.max_buffer_size, self.resolver)\n\n    def _release_fetch(self, key):\n        del self.active[key]\n        self._process_queue()\n\n    def _remove_timeout(self, key):\n        if key in self.waiting:\n            request, callback, timeout_handle = self.waiting[key]\n            self.io_loop.remove_timeout(timeout_handle)\n            del self.waiting[key]\n\n    def _on_timeout(self, key):\n        request, callback, timeout_handle = self.waiting[key]\n        self.queue.remove((key, request, callback))\n        timeout_response = HTTPResponse(\n                request, 599, error=HTTPError(599, \"Timeout\"),\n                request_time=self.io_loop.time() - request.start_time)\n        self.io_loop.add_callback(callback, timeout_response)\n        del self.waiting[key]",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 36,
                                "end_lineno": 136,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "tornado/simple_httpclient.py",
                            "type": "class",
                            "name": "SimpleAsyncHTTPClient",
                            "content": "class SimpleAsyncHTTPClient(AsyncHTTPClient):\n    \"\"\"Non-blocking HTTP client with no external dependencies.\n\n    This class implements an HTTP 1.1 client on top of Tornado's IOStreams.\n    It does not currently implement all applicable parts of the HTTP\n    specification, but it does enough to work with major web service APIs.\n\n    Some features found in the curl-based AsyncHTTPClient are not yet\n    supported.  In particular, proxies are not supported, connections\n    are not reused, and callers cannot select the network interface to be\n    used.\n    \"\"\"\n    def initialize(self, io_loop, max_clients=10,\n                   hostname_mapping=None, max_buffer_size=104857600,\n                   resolver=None, defaults=None):\n        \"\"\"Creates a AsyncHTTPClient.\n\n        Only a single AsyncHTTPClient instance exists per IOLoop\n        in order to provide limitations on the number of pending connections.\n        force_instance=True may be used to suppress this behavior.\n\n        max_clients is the number of concurrent requests that can be\n        in progress.  Note that this arguments are only used when the\n        client is first created, and will be ignored when an existing\n        client is reused.\n\n        hostname_mapping is a dictionary mapping hostnames to IP addresses.\n        It can be used to make local DNS changes when modifying system-wide\n        settings like /etc/hosts is not possible or desirable (e.g. in\n        unittests).\n\n        max_buffer_size is the number of bytes that can be read by IOStream. It\n        defaults to 100mb.\n        \"\"\"\n        super(SimpleAsyncHTTPClient, self).initialize(io_loop,\n                                                      defaults=defaults)\n        self.max_clients = max_clients\n        self.queue = collections.deque()\n        self.active = {}\n        self.waiting = {}\n        self.max_buffer_size = max_buffer_size\n        if resolver:\n            self.resolver = resolver\n            self.own_resolver = False\n        else:\n            self.resolver = Resolver(io_loop=io_loop)\n            self.own_resolver = True\n        if hostname_mapping is not None:\n            self.resolver = OverrideResolver(resolver=self.resolver,\n                                             mapping=hostname_mapping)\n\n    def close(self):\n        super(SimpleAsyncHTTPClient, self).close()\n        if self.own_resolver:\n            self.resolver.close()\n\n    def fetch_impl(self, request, callback):\n        key = object()\n        self.queue.append((key, request, callback))\n        if not len(self.active) < self.max_clients:\n            timeout_handle = self.io_loop.add_timeout(\n                    request.start_time + request.async_timeout,\n                    functools.partial(self._on_timeout, key))\n            self.waiting[key] = (request, callback, timeout_handle)\n        self._process_queue()\n        if self.queue:\n            gen_log.debug(\"max_clients limit reached, request queued. \"\n                          \"%d active, %d queued requests.\" % (\n                              len(self.active), len(self.queue)))\n\n    def _process_queue(self):\n        with stack_context.NullContext():\n            while self.queue and len(self.active) < self.max_clients:\n                key, request, callback = self.queue.popleft()\n                self._remove_timeout(key)\n                self.active[key] = (request, callback)\n                release_callback = functools.partial(self._release_fetch, key)\n                self._handle_request(request, release_callback, callback)\n\n    def _handle_request(self, request, release_callback, final_callback):\n        _HTTPConnection(self.io_loop, self, request, release_callback,\n                        final_callback, self.max_buffer_size, self.resolver)\n\n    def _release_fetch(self, key):\n        del self.active[key]\n        self._process_queue()\n\n    def _remove_timeout(self, key):\n        if key in self.waiting:\n            request, callback, timeout_handle = self.waiting[key]\n            self.io_loop.remove_timeout(timeout_handle)\n            del self.waiting[key]\n\n    def _on_timeout(self, key):\n        request, callback, timeout_handle = self.waiting[key]\n        self.queue.remove((key, request, callback))\n        timeout_response = HTTPResponse(\n                request, 599, error=HTTPError(599, \"Timeout\"),\n                request_time=self.io_loop.time() - request.start_time)\n        self.io_loop.add_callback(callback, timeout_response)\n        del self.waiting[key]",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 36,
                            "end_lineno": 136,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "from __future__ import absolute_import, division, print_function, with_statement\n\nimport collections\nfrom contextlib import closing\nimport errno\nimport gzip\nimport logging\nimport os\nimport re\nimport socket\nimport sys\n\nfrom tornado.httpclient import AsyncHTTPClient\nfrom tornado.httputil import HTTPHeaders\nfrom tornado.ioloop import IOLoop\nfrom tornado.log import gen_log\nfrom tornado.simple_httpclient import SimpleAsyncHTTPClient, _DEFAULT_CA_CERTS\nfrom tornado.test.httpclient_test import ChunkHandler, CountdownHandler, HelloWorldHandler\nfrom tornado.test import httpclient_test\nfrom tornado.testing import AsyncHTTPTestCase, AsyncHTTPSTestCase, AsyncTestCase, bind_unused_port, ExpectLog\nfrom tornado.test.util import unittest, skipOnTravis\nfrom tornado.web import RequestHandler, Application, asynchronous, url\n\n\nclass SimpleHTTPClientCommonTestCase(httpclient_test.HTTPClientCommonTestCase):\n    def get_http_client(self):\n        client = SimpleAsyncHTTPClient(io_loop=self.io_loop,\n                                       force_instance=True)\n        self.assertTrue(isinstance(client, SimpleAsyncHTTPClient))\n        return client\n\n\nclass TriggerHandler(RequestHandler):\n    def initialize(self, queue, wake_callback):\n        self.queue = queue\n        self.wake_callback = wake_callback\n\n    @asynchronous\n    def get(self):\n        logging.debug(\"queuing trigger\")\n        self.queue.append(self.finish)\n        if self.get_argument(\"wake\", \"true\") == \"true\":\n            self.wake_callback()\n\n\nclass HangHandler(RequestHandler):\n    @asynchronous\n    def get(self):\n        pass\n\n\nclass ContentLengthHandler(RequestHandler):\n    def get(self):\n        self.set_header(\"Content-Length\", self.get_argument(\"value\"))\n        self.write(\"ok\")\n\n\nclass HeadHandler(RequestHandler):\n    def head(self):\n        self.set_header(\"Content-Length\", \"7\")\n\n\nclass OptionsHandler(RequestHandler):\n    def options(self):\n        self.set_header(\"Access-Control-Allow-Origin\", \"*\")\n        self.write(\"ok\")\n\n\nclass NoContentHandler(RequestHandler):\n    def get(self):\n        if self.get_argument(\"error\", None):\n            self.set_header(\"Content-Length\", \"7\")\n        self.set_status(204)\n\n\nclass SeeOtherPostHandler(RequestHandler):\n    def post(self):\n        redirect_code = int(self.request.body)\n        assert redirect_code in (302, 303), \"unexpected body %r\" % self.request.body\n        self.set_header(\"Location\", \"/see_other_get\")\n        self.set_status(redirect_code)\n\n\nclass SeeOtherGetHandler(RequestHandler):\n    def get(self):\n        if self.request.body:\n            raise Exception(\"unexpected body %r\" % self.request.body)\n        self.write(\"ok\")\n\n\nclass HostEchoHandler(RequestHandler):\n    def get(self):\n        self.write(self.request.headers[\"Host\"])\n\n\nclass SimpleHTTPClientTestMixin(object):\n    def get_app(self):\n        # callable objects to finish pending /trigger requests\n        self.triggers = collections.deque()\n        return Application([\n            url(\"/trigger\", TriggerHandler, dict(queue=self.triggers,\n                                                 wake_callback=self.stop)),\n            url(\"/chunk\", ChunkHandler),\n            url(\"/countdown/([0-9]+)\", CountdownHandler, name=\"countdown\"),\n            url(\"/hang\", HangHandler),\n            url(\"/hello\", HelloWorldHandler),\n            url(\"/content_length\", ContentLengthHandler),\n            url(\"/head\", HeadHandler),\n            url(\"/options\", OptionsHandler),\n            url(\"/no_content\", NoContentHandler),\n            url(\"/see_other_post\", SeeOtherPostHandler),\n            url(\"/see_other_get\", SeeOtherGetHandler),\n            url(\"/host_echo\", HostEchoHandler),\n        ], gzip=True)\n\n    def test_singleton(self):\n        # Class \"constructor\" reuses objects on the same IOLoop\n        self.assertTrue(SimpleAsyncHTTPClient(self.io_loop) is\n                        SimpleAsyncHTTPClient(self.io_loop))\n        # unless force_instance is used\n        self.assertTrue(SimpleAsyncHTTPClient(self.io_loop) is not\n                        SimpleAsyncHTTPClient(self.io_loop,\n                                              force_instance=True))\n        # different IOLoops use different objects\n        io_loop2 = IOLoop()\n        self.assertTrue(SimpleAsyncHTTPClient(self.io_loop) is not\n                        SimpleAsyncHTTPClient(io_loop2))\n\n    def test_connection_limit(self):\n        with closing(self.create_client(max_clients=2)) as client:\n            self.assertEqual(client.max_clients, 2)\n            seen = []\n            # Send 4 requests.  Two can be sent immediately, while the others\n            # will be queued\n            for i in range(4):\n                client.fetch(self.get_url(\"/trigger\"),\n                             lambda response, i=i: (seen.append(i), self.stop()))\n            self.wait(condition=lambda: len(self.triggers) == 2)\n            self.assertEqual(len(client.queue), 2)\n\n            # Finish the first two requests and let the next two through\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: (len(self.triggers) == 2 and\n                                         len(seen) == 2))\n            self.assertEqual(set(seen), set([0, 1]))\n            self.assertEqual(len(client.queue), 0)\n\n            # Finish all the pending requests\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: len(seen) == 4)\n            self.assertEqual(set(seen), set([0, 1, 2, 3]))\n            self.assertEqual(len(self.triggers), 0)\n\n    def test_redirect_connection_limit(self):\n        # following redirects should not consume additional connections\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/countdown/3'), self.stop,\n                         max_redirects=3)\n            response = self.wait()\n            response.rethrow()\n\n    def test_default_certificates_exist(self):\n        open(_DEFAULT_CA_CERTS).close()\n\n    def test_gzip(self):\n        # All the tests in this file should be using gzip, but this test\n        # ensures that it is in fact getting compressed.\n        # Setting Accept-Encoding manually bypasses the client's\n        # decompression so we can see the raw data.\n        response = self.fetch(\"/chunk\", use_gzip=False,\n                              headers={\"Accept-Encoding\": \"gzip\"})\n        self.assertEqual(response.headers[\"Content-Encoding\"], \"gzip\")\n        self.assertNotEqual(response.body, b\"asdfqwer\")\n        # Our test data gets bigger when gzipped.  Oops.  :)\n        self.assertEqual(len(response.body), 34)\n        f = gzip.GzipFile(mode=\"r\", fileobj=response.buffer)\n        self.assertEqual(f.read(), b\"asdfqwer\")\n\n    def test_max_redirects(self):\n        response = self.fetch(\"/countdown/5\", max_redirects=3)\n        self.assertEqual(302, response.code)\n        # We requested 5, followed three redirects for 4, 3, 2, then the last\n        # unfollowed redirect is to 1.\n        self.assertTrue(response.request.url.endswith(\"/countdown/5\"))\n        self.assertTrue(response.effective_url.endswith(\"/countdown/2\"))\n        self.assertTrue(response.headers[\"Location\"].endswith(\"/countdown/1\"))\n\n    def test_header_reuse(self):\n        # Apps may reuse a headers object if they are only passing in constant\n        # headers like user-agent.  The header object should not be modified.\n        headers = HTTPHeaders({'User-Agent': 'Foo'})\n        self.fetch(\"/hello\", headers=headers)\n        self.assertEqual(list(headers.get_all()), [('User-Agent', 'Foo')])\n\n    def test_see_other_redirect(self):\n        for code in (302, 303):\n            response = self.fetch(\"/see_other_post\", method=\"POST\", body=\"%d\" % code)\n            self.assertEqual(200, response.code)\n            self.assertTrue(response.request.url.endswith(\"/see_other_post\"))\n            self.assertTrue(response.effective_url.endswith(\"/see_other_get\"))\n            # request is the original request, is a POST still\n            self.assertEqual(\"POST\", response.request.method)\n\n    @skipOnTravis\n    def test_request_timeout(self):\n        response = self.fetch('/trigger?wake=false', request_timeout=0.1)\n        self.assertEqual(response.code, 599)\n        self.assertTrue(0.099 < response.request_time < 0.15, response.request_time)\n        self.assertEqual(str(response.error), \"HTTP 599: Timeout\")\n        # trigger the hanging request to let it clean up after itself\n        self.triggers.popleft()()\n\n    @unittest.skipIf(not socket.has_ipv6, 'ipv6 support not present')\n    def test_ipv6(self):\n        try:\n            self.http_server.listen(self.get_http_port(), address='::1')\n        except socket.gaierror as e:\n            if e.args[0] == socket.EAI_ADDRFAMILY:\n                # python supports ipv6, but it's not configured on the network\n                # interface, so skip this test.\n                return\n            raise\n        url = self.get_url(\"/hello\").replace(\"localhost\", \"[::1]\")\n\n        # ipv6 is currently disabled by default and must be explicitly requested\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertEqual(response.code, 599)\n\n        self.http_client.fetch(url, self.stop, allow_ipv6=True)\n        response = self.wait()\n        self.assertEqual(response.body, b\"Hello world!\")\n\n    def test_multiple_content_length_accepted(self):\n        response = self.fetch(\"/content_length?value=2,2\")\n        self.assertEqual(response.body, b\"ok\")\n        response = self.fetch(\"/content_length?value=2,%202,2\")\n        self.assertEqual(response.body, b\"ok\")\n\n        response = self.fetch(\"/content_length?value=2,4\")\n        self.assertEqual(response.code, 599)\n        response = self.fetch(\"/content_length?value=2,%202,3\")\n        self.assertEqual(response.code, 599)\n\n    def test_head_request(self):\n        response = self.fetch(\"/head\", method=\"HEAD\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"7\")\n        self.assertFalse(response.body)\n\n    def test_options_request(self):\n        response = self.fetch(\"/options\", method=\"OPTIONS\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"2\")\n        self.assertEqual(response.headers[\"access-control-allow-origin\"], \"*\")\n        self.assertEqual(response.body, b\"ok\")\n\n    def test_no_content(self):\n        response = self.fetch(\"/no_content\")\n        self.assertEqual(response.code, 204)\n        # 204 status doesn't need a content-length, but tornado will\n        # add a zero content-length anyway.\n        self.assertEqual(response.headers[\"Content-length\"], \"0\")\n\n        # 204 status with non-zero content length is malformed\n        response = self.fetch(\"/no_content?error=1\")\n        self.assertEqual(response.code, 599)\n\n    def test_host_header(self):\n        host_re = re.compile(b\"^localhost:[0-9]+$\")\n        response = self.fetch(\"/host_echo\")\n        self.assertTrue(host_re.match(response.body))\n\n        url = self.get_url(\"/host_echo\").replace(\"http://\", \"http://me:secret@\")\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertTrue(host_re.match(response.body), response.body)\n\n    def test_connection_refused(self):\n        server_socket, port = bind_unused_port()\n        server_socket.close()\n        with ExpectLog(gen_log, \".*\", required=False):\n            self.http_client.fetch(\"http://localhost:%d/\" % port, self.stop)\n            response = self.wait()\n        self.assertEqual(599, response.code)\n\n        if sys.platform != 'cygwin':\n            # cygwin returns EPERM instead of ECONNREFUSED here\n            self.assertTrue(str(errno.ECONNREFUSED) in str(response.error),\n                            response.error)\n            # This is usually \"Connection refused\".\n            # On windows, strerror is broken and returns \"Unknown error\".\n            expected_message = os.strerror(errno.ECONNREFUSED)\n            self.assertTrue(expected_message in str(response.error),\n                            response.error)\n\n\nclass SimpleHTTPClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPTestCase):\n    def setUp(self):\n        super(SimpleHTTPClientTestCase, self).setUp()\n        self.http_client = self.create_client()\n\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(self.io_loop, force_instance=True,\n                                     **kwargs)\n\n\nclass SimpleHTTPSClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPSTestCase):\n    def setUp(self):\n        super(SimpleHTTPSClientTestCase, self).setUp()\n        self.http_client = self.create_client()\n\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(self.io_loop, force_instance=True,\n                                     defaults=dict(validate_cert=False),\n                                     **kwargs)\n\n\nclass CreateAsyncHTTPClientTestCase(AsyncTestCase):\n    def setUp(self):\n        super(CreateAsyncHTTPClientTestCase, self).setUp()\n        self.saved = AsyncHTTPClient._save_configuration()\n\n    def tearDown(self):\n        AsyncHTTPClient._restore_configuration(self.saved)\n        super(CreateAsyncHTTPClientTestCase, self).tearDown()\n\n    def test_max_clients(self):\n        AsyncHTTPClient.configure(SimpleAsyncHTTPClient)\n        with closing(AsyncHTTPClient(\n                self.io_loop, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 10)\n        with closing(AsyncHTTPClient(\n                self.io_loop, max_clients=11, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 11)\n\n        # Now configure max_clients statically and try overriding it\n        # with each way max_clients can be passed\n        AsyncHTTPClient.configure(SimpleAsyncHTTPClient, max_clients=12)\n        with closing(AsyncHTTPClient(\n                self.io_loop, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 12)\n        with closing(AsyncHTTPClient(\n                self.io_loop, max_clients=13, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 13)\n        with closing(AsyncHTTPClient(\n                self.io_loop, max_clients=14, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 14)\n\n\nclass HTTP100ContinueTestCase(AsyncHTTPTestCase):\n    def respond_100(self, request):\n        self.request = request\n        self.request.connection.stream.write(\n            b\"HTTP/1.1 100 CONTINUE\\r\\n\\r\\n\",\n            self.respond_200)\n\n    def respond_200(self):\n        self.request.connection.stream.write(\n            b\"HTTP/1.1 200 OK\\r\\nContent-Length: 1\\r\\n\\r\\nA\",\n            self.request.connection.stream.close)\n\n    def get_app(self):\n        # Not a full Application, but works as an HTTPServer callback\n        return self.respond_100\n\n    def test_100_continue(self):\n        res = self.fetch('/')\n        self.assertEqual(res.body, b'A')\n\n\nclass HostnameMappingTestCase(AsyncHTTPTestCase):\n    def setUp(self):\n        super(HostnameMappingTestCase, self).setUp()\n        self.http_client = SimpleAsyncHTTPClient(\n            self.io_loop,\n            hostname_mapping={\n                'www.example.com': '127.0.0.1',\n                ('foo.example.com', 8000): ('127.0.0.1', self.get_http_port()),\n            })\n\n    def get_app(self):\n        return Application([url(\"/hello\", HelloWorldHandler), ])\n\n    def test_hostname_mapping(self):\n        self.http_client.fetch(\n            'http://www.example.com:%d/hello' % self.get_http_port(), self.stop)\n        response = self.wait()\n        response.rethrow()\n        self.assertEqual(response.body, b'Hello world!')\n\n    def test_port_mapping(self):\n        self.http_client.fetch('http://foo.example.com:8000/hello', self.stop)\n        response = self.wait()\n        response.rethrow()\n        self.assertEqual(response.body, b'Hello world!')\n\n\nclass HeavyloadAsyncHTTPClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPTestCase):\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(self.io_loop, force_instance=True, **kwargs)\n\n    def test_heavyload_timeout(self):\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/trigger?wake=false'), self.stop, request_timeout=10)\n            client.fetch(self.get_url('/hello'), self.stop, async_timeout=3)\n            response = self.wait()\n\n            self.assertEqual(response.code, 599)\n            self.assertTrue(2.9 < response.request_time < 3.1, response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout\")\n            self.triggers.popleft()()\n\n\n",
            "new_file_content": "from __future__ import absolute_import, division, print_function, with_statement\n\nimport collections\nfrom contextlib import closing\nimport errno\nimport gzip\nimport logging\nimport os\nimport re\nimport socket\nimport sys\n\nfrom tornado.httpclient import AsyncHTTPClient\nfrom tornado.httputil import HTTPHeaders\nfrom tornado.ioloop import IOLoop\nfrom tornado.log import gen_log\nfrom tornado.simple_httpclient import SimpleAsyncHTTPClient, _DEFAULT_CA_CERTS\nfrom tornado.test.httpclient_test import ChunkHandler, CountdownHandler, HelloWorldHandler\nfrom tornado.test import httpclient_test\nfrom tornado.testing import AsyncHTTPTestCase, AsyncHTTPSTestCase, AsyncTestCase, bind_unused_port, ExpectLog\nfrom tornado.test.util import unittest, skipOnTravis\nfrom tornado.web import RequestHandler, Application, asynchronous, url\n\n\nclass SimpleHTTPClientCommonTestCase(httpclient_test.HTTPClientCommonTestCase):\n    def get_http_client(self):\n        client = SimpleAsyncHTTPClient(io_loop=self.io_loop,\n                                       force_instance=True)\n        self.assertTrue(isinstance(client, SimpleAsyncHTTPClient))\n        return client\n\n\nclass TriggerHandler(RequestHandler):\n    def initialize(self, queue, wake_callback):\n        self.queue = queue\n        self.wake_callback = wake_callback\n\n    @asynchronous\n    def get(self):\n        logging.debug(\"queuing trigger\")\n        self.queue.append(self.finish)\n        if self.get_argument(\"wake\", \"true\") == \"true\":\n            self.wake_callback()\n\n\nclass HangHandler(RequestHandler):\n    @asynchronous\n    def get(self):\n        pass\n\n\nclass ContentLengthHandler(RequestHandler):\n    def get(self):\n        self.set_header(\"Content-Length\", self.get_argument(\"value\"))\n        self.write(\"ok\")\n\n\nclass HeadHandler(RequestHandler):\n    def head(self):\n        self.set_header(\"Content-Length\", \"7\")\n\n\nclass OptionsHandler(RequestHandler):\n    def options(self):\n        self.set_header(\"Access-Control-Allow-Origin\", \"*\")\n        self.write(\"ok\")\n\n\nclass NoContentHandler(RequestHandler):\n    def get(self):\n        if self.get_argument(\"error\", None):\n            self.set_header(\"Content-Length\", \"7\")\n        self.set_status(204)\n\n\nclass SeeOtherPostHandler(RequestHandler):\n    def post(self):\n        redirect_code = int(self.request.body)\n        assert redirect_code in (302, 303), \"unexpected body %r\" % self.request.body\n        self.set_header(\"Location\", \"/see_other_get\")\n        self.set_status(redirect_code)\n\n\nclass SeeOtherGetHandler(RequestHandler):\n    def get(self):\n        if self.request.body:\n            raise Exception(\"unexpected body %r\" % self.request.body)\n        self.write(\"ok\")\n\n\nclass HostEchoHandler(RequestHandler):\n    def get(self):\n        self.write(self.request.headers[\"Host\"])\n\n\nclass SimpleHTTPClientTestMixin(object):\n    def get_app(self):\n        # callable objects to finish pending /trigger requests\n        self.triggers = collections.deque()\n        return Application([\n            url(\"/trigger\", TriggerHandler, dict(queue=self.triggers,\n                                                 wake_callback=self.stop)),\n            url(\"/chunk\", ChunkHandler),\n            url(\"/countdown/([0-9]+)\", CountdownHandler, name=\"countdown\"),\n            url(\"/hang\", HangHandler),\n            url(\"/hello\", HelloWorldHandler),\n            url(\"/content_length\", ContentLengthHandler),\n            url(\"/head\", HeadHandler),\n            url(\"/options\", OptionsHandler),\n            url(\"/no_content\", NoContentHandler),\n            url(\"/see_other_post\", SeeOtherPostHandler),\n            url(\"/see_other_get\", SeeOtherGetHandler),\n            url(\"/host_echo\", HostEchoHandler),\n        ], gzip=True)\n\n    def test_singleton(self):\n        # Class \"constructor\" reuses objects on the same IOLoop\n        self.assertTrue(SimpleAsyncHTTPClient(self.io_loop) is\n                        SimpleAsyncHTTPClient(self.io_loop))\n        # unless force_instance is used\n        self.assertTrue(SimpleAsyncHTTPClient(self.io_loop) is not\n                        SimpleAsyncHTTPClient(self.io_loop,\n                                              force_instance=True))\n        # different IOLoops use different objects\n        io_loop2 = IOLoop()\n        self.assertTrue(SimpleAsyncHTTPClient(self.io_loop) is not\n                        SimpleAsyncHTTPClient(io_loop2))\n\n    def test_connection_limit(self):\n        with closing(self.create_client(max_clients=2)) as client:\n            self.assertEqual(client.max_clients, 2)\n            seen = []\n            # Send 4 requests.  Two can be sent immediately, while the others\n            # will be queued\n            for i in range(4):\n                client.fetch(self.get_url(\"/trigger\"),\n                             lambda response, i=i: (seen.append(i), self.stop()))\n            self.wait(condition=lambda: len(self.triggers) == 2)\n            self.assertEqual(len(client.queue), 2)\n\n            # Finish the first two requests and let the next two through\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: (len(self.triggers) == 2 and\n                                         len(seen) == 2))\n            self.assertEqual(set(seen), set([0, 1]))\n            self.assertEqual(len(client.queue), 0)\n\n            # Finish all the pending requests\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: len(seen) == 4)\n            self.assertEqual(set(seen), set([0, 1, 2, 3]))\n            self.assertEqual(len(self.triggers), 0)\n\n    def test_redirect_connection_limit(self):\n        # following redirects should not consume additional connections\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/countdown/3'), self.stop,\n                         max_redirects=3)\n            response = self.wait()\n            response.rethrow()\n\n    def test_default_certificates_exist(self):\n        open(_DEFAULT_CA_CERTS).close()\n\n    def test_gzip(self):\n        # All the tests in this file should be using gzip, but this test\n        # ensures that it is in fact getting compressed.\n        # Setting Accept-Encoding manually bypasses the client's\n        # decompression so we can see the raw data.\n        response = self.fetch(\"/chunk\", use_gzip=False,\n                              headers={\"Accept-Encoding\": \"gzip\"})\n        self.assertEqual(response.headers[\"Content-Encoding\"], \"gzip\")\n        self.assertNotEqual(response.body, b\"asdfqwer\")\n        # Our test data gets bigger when gzipped.  Oops.  :)\n        self.assertEqual(len(response.body), 34)\n        f = gzip.GzipFile(mode=\"r\", fileobj=response.buffer)\n        self.assertEqual(f.read(), b\"asdfqwer\")\n\n    def test_max_redirects(self):\n        response = self.fetch(\"/countdown/5\", max_redirects=3)\n        self.assertEqual(302, response.code)\n        # We requested 5, followed three redirects for 4, 3, 2, then the last\n        # unfollowed redirect is to 1.\n        self.assertTrue(response.request.url.endswith(\"/countdown/5\"))\n        self.assertTrue(response.effective_url.endswith(\"/countdown/2\"))\n        self.assertTrue(response.headers[\"Location\"].endswith(\"/countdown/1\"))\n\n    def test_header_reuse(self):\n        # Apps may reuse a headers object if they are only passing in constant\n        # headers like user-agent.  The header object should not be modified.\n        headers = HTTPHeaders({'User-Agent': 'Foo'})\n        self.fetch(\"/hello\", headers=headers)\n        self.assertEqual(list(headers.get_all()), [('User-Agent', 'Foo')])\n\n    def test_see_other_redirect(self):\n        for code in (302, 303):\n            response = self.fetch(\"/see_other_post\", method=\"POST\", body=\"%d\" % code)\n            self.assertEqual(200, response.code)\n            self.assertTrue(response.request.url.endswith(\"/see_other_post\"))\n            self.assertTrue(response.effective_url.endswith(\"/see_other_get\"))\n            # request is the original request, is a POST still\n            self.assertEqual(\"POST\", response.request.method)\n\n    @skipOnTravis\n    def test_request_timeout(self):\n        response = self.fetch('/trigger?wake=false', request_timeout=0.1)\n        self.assertEqual(response.code, 599)\n        self.assertTrue(0.099 < response.request_time < 0.15, response.request_time)\n        self.assertEqual(str(response.error), \"HTTP 599: Timeout\")\n        # trigger the hanging request to let it clean up after itself\n        self.triggers.popleft()()\n\n    @unittest.skipIf(not socket.has_ipv6, 'ipv6 support not present')\n    def test_ipv6(self):\n        try:\n            self.http_server.listen(self.get_http_port(), address='::1')\n        except socket.gaierror as e:\n            if e.args[0] == socket.EAI_ADDRFAMILY:\n                # python supports ipv6, but it's not configured on the network\n                # interface, so skip this test.\n                return\n            raise\n        url = self.get_url(\"/hello\").replace(\"localhost\", \"[::1]\")\n\n        # ipv6 is currently disabled by default and must be explicitly requested\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertEqual(response.code, 599)\n\n        self.http_client.fetch(url, self.stop, allow_ipv6=True)\n        response = self.wait()\n        self.assertEqual(response.body, b\"Hello world!\")\n\n    def test_multiple_content_length_accepted(self):\n        response = self.fetch(\"/content_length?value=2,2\")\n        self.assertEqual(response.body, b\"ok\")\n        response = self.fetch(\"/content_length?value=2,%202,2\")\n        self.assertEqual(response.body, b\"ok\")\n\n        response = self.fetch(\"/content_length?value=2,4\")\n        self.assertEqual(response.code, 599)\n        response = self.fetch(\"/content_length?value=2,%202,3\")\n        self.assertEqual(response.code, 599)\n\n    def test_head_request(self):\n        response = self.fetch(\"/head\", method=\"HEAD\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"7\")\n        self.assertFalse(response.body)\n\n    def test_options_request(self):\n        response = self.fetch(\"/options\", method=\"OPTIONS\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"2\")\n        self.assertEqual(response.headers[\"access-control-allow-origin\"], \"*\")\n        self.assertEqual(response.body, b\"ok\")\n\n    def test_no_content(self):\n        response = self.fetch(\"/no_content\")\n        self.assertEqual(response.code, 204)\n        # 204 status doesn't need a content-length, but tornado will\n        # add a zero content-length anyway.\n        self.assertEqual(response.headers[\"Content-length\"], \"0\")\n\n        # 204 status with non-zero content length is malformed\n        response = self.fetch(\"/no_content?error=1\")\n        self.assertEqual(response.code, 599)\n\n    def test_host_header(self):\n        host_re = re.compile(b\"^localhost:[0-9]+$\")\n        response = self.fetch(\"/host_echo\")\n        self.assertTrue(host_re.match(response.body))\n\n        url = self.get_url(\"/host_echo\").replace(\"http://\", \"http://me:secret@\")\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertTrue(host_re.match(response.body), response.body)\n\n    def test_connection_refused(self):\n        server_socket, port = bind_unused_port()\n        server_socket.close()\n        with ExpectLog(gen_log, \".*\", required=False):\n            self.http_client.fetch(\"http://localhost:%d/\" % port, self.stop)\n            response = self.wait()\n        self.assertEqual(599, response.code)\n\n        if sys.platform != 'cygwin':\n            # cygwin returns EPERM instead of ECONNREFUSED here\n            self.assertTrue(str(errno.ECONNREFUSED) in str(response.error),\n                            response.error)\n            # This is usually \"Connection refused\".\n            # On windows, strerror is broken and returns \"Unknown error\".\n            expected_message = os.strerror(errno.ECONNREFUSED)\n            self.assertTrue(expected_message in str(response.error),\n                            response.error)\n\n\nclass SimpleHTTPClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPTestCase):\n    def setUp(self):\n        super(SimpleHTTPClientTestCase, self).setUp()\n        self.http_client = self.create_client()\n\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(self.io_loop, force_instance=True,\n                                     **kwargs)\n\n\nclass SimpleHTTPSClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPSTestCase):\n    def setUp(self):\n        super(SimpleHTTPSClientTestCase, self).setUp()\n        self.http_client = self.create_client()\n\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(self.io_loop, force_instance=True,\n                                     defaults=dict(validate_cert=False),\n                                     **kwargs)\n\n\nclass CreateAsyncHTTPClientTestCase(AsyncTestCase):\n    def setUp(self):\n        super(CreateAsyncHTTPClientTestCase, self).setUp()\n        self.saved = AsyncHTTPClient._save_configuration()\n\n    def tearDown(self):\n        AsyncHTTPClient._restore_configuration(self.saved)\n        super(CreateAsyncHTTPClientTestCase, self).tearDown()\n\n    def test_max_clients(self):\n        AsyncHTTPClient.configure(SimpleAsyncHTTPClient)\n        with closing(AsyncHTTPClient(\n                self.io_loop, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 10)\n        with closing(AsyncHTTPClient(\n                self.io_loop, max_clients=11, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 11)\n\n        # Now configure max_clients statically and try overriding it\n        # with each way max_clients can be passed\n        AsyncHTTPClient.configure(SimpleAsyncHTTPClient, max_clients=12)\n        with closing(AsyncHTTPClient(\n                self.io_loop, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 12)\n        with closing(AsyncHTTPClient(\n                self.io_loop, max_clients=13, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 13)\n        with closing(AsyncHTTPClient(\n                self.io_loop, max_clients=14, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 14)\n\n\nclass HTTP100ContinueTestCase(AsyncHTTPTestCase):\n    def respond_100(self, request):\n        self.request = request\n        self.request.connection.stream.write(\n            b\"HTTP/1.1 100 CONTINUE\\r\\n\\r\\n\",\n            self.respond_200)\n\n    def respond_200(self):\n        self.request.connection.stream.write(\n            b\"HTTP/1.1 200 OK\\r\\nContent-Length: 1\\r\\n\\r\\nA\",\n            self.request.connection.stream.close)\n\n    def get_app(self):\n        # Not a full Application, but works as an HTTPServer callback\n        return self.respond_100\n\n    def test_100_continue(self):\n        res = self.fetch('/')\n        self.assertEqual(res.body, b'A')\n\n\nclass HostnameMappingTestCase(AsyncHTTPTestCase):\n    def setUp(self):\n        super(HostnameMappingTestCase, self).setUp()\n        self.http_client = SimpleAsyncHTTPClient(\n            self.io_loop,\n            hostname_mapping={\n                'www.example.com': '127.0.0.1',\n                ('foo.example.com', 8000): ('127.0.0.1', self.get_http_port()),\n            })\n\n    def get_app(self):\n        return Application([url(\"/hello\", HelloWorldHandler), ])\n\n    def test_hostname_mapping(self):\n        self.http_client.fetch(\n            'http://www.example.com:%d/hello' % self.get_http_port(), self.stop)\n        response = self.wait()\n        response.rethrow()\n        self.assertEqual(response.body, b'Hello world!')\n\n    def test_port_mapping(self):\n        self.http_client.fetch('http://foo.example.com:8000/hello', self.stop)\n        response = self.wait()\n        response.rethrow()\n        self.assertEqual(response.body, b'Hello world!')\n\n\nclass HeavyloadAsyncHTTPClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPTestCase):\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(self.io_loop, force_instance=True, **kwargs)\n\n    def test_heavyload_timeout(self):\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/trigger?wake=false'), self.stop, request_timeout=10)\n            client.fetch(self.get_url('/hello'), self.stop, connect_timeout=3)\n            response = self.wait()\n\n            self.assertEqual(response.code, 599)\n            self.assertTrue(2.9 < response.request_time < 3.1, response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout\")\n            self.triggers.popleft()()\n\n\n",
            "header": {
                "file": {
                    "path": "tornado/test/simple_httpclient_test.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "fc681898",
                "new_commit_hash": "07def1b8",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tornado/test/simple_httpclient_test.py"
            },
            "plus_file": {
                "path": "b/tornado/test/simple_httpclient_test.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 405,
                            "length": 7
                        },
                        "new_range": {
                            "start": 405,
                            "length": 7
                        },
                        "section": "class HeavyloadAsyncHTTPClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPTestC"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    def test_heavyload_timeout(self):",
                                "type": "context"
                            },
                            {
                                "content": "        with closing(self.create_client(max_clients=1)) as client:",
                                "type": "context"
                            },
                            {
                                "content": "            client.fetch(self.get_url('/trigger?wake=false'), self.stop, request_timeout=10)",
                                "type": "context"
                            },
                            {
                                "content": "            client.fetch(self.get_url('/hello'), self.stop, async_timeout=3)",
                                "type": "deleted"
                            },
                            {
                                "content": "            client.fetch(self.get_url('/hello'), self.stop, connect_timeout=3)",
                                "type": "added"
                            },
                            {
                                "content": "            response = self.wait()",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "            self.assertEqual(response.code, 599)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/test/simple_httpclient_test.py",
                            "type": "method",
                            "name": "HeavyloadAsyncHTTPClientTestCase.test_heavyload_timeout",
                            "content": "class HeavyloadAsyncHTTPClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPTestCase):\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(self.io_loop, force_instance=True, **kwargs)\n\n    def test_heavyload_timeout(self):\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/trigger?wake=false'), self.stop, request_timeout=10)\n            client.fetch(self.get_url('/hello'), self.stop, async_timeout=3)\n            response = self.wait()\n\n            self.assertEqual(response.code, 599)\n            self.assertTrue(2.9 < response.request_time < 3.1, response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout\")\n            self.triggers.popleft()()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 405,
                            "end_lineno": 414,
                            "parent": {
                                "file_name": "tornado/test/simple_httpclient_test.py",
                                "type": "class",
                                "name": "HeavyloadAsyncHTTPClientTestCase",
                                "content": "class HeavyloadAsyncHTTPClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPTestCase):\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(self.io_loop, force_instance=True, **kwargs)\n\n    def test_heavyload_timeout(self):\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/trigger?wake=false'), self.stop, request_timeout=10)\n            client.fetch(self.get_url('/hello'), self.stop, async_timeout=3)\n            response = self.wait()\n\n            self.assertEqual(response.code, 599)\n            self.assertTrue(2.9 < response.request_time < 3.1, response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout\")\n            self.triggers.popleft()()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 401,
                                "end_lineno": 414,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "tornado/test/simple_httpclient_test.py",
                            "type": "class",
                            "name": "HeavyloadAsyncHTTPClientTestCase",
                            "content": "class HeavyloadAsyncHTTPClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPTestCase):\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(self.io_loop, force_instance=True, **kwargs)\n\n    def test_heavyload_timeout(self):\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/trigger?wake=false'), self.stop, request_timeout=10)\n            client.fetch(self.get_url('/hello'), self.stop, async_timeout=3)\n            response = self.wait()\n\n            self.assertEqual(response.code, 599)\n            self.assertTrue(2.9 < response.request_time < 3.1, response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout\")\n            self.triggers.popleft()()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 401,
                            "end_lineno": 414,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "2d5f396407f9ce3c19751d1b6205a0f04143d3d6^",
    "new_commit_hash": "2d5f396407f9ce3c19751d1b6205a0f04143d3d6",
    "commit_message": "Remove `async_timeout` and use `connect_timeout` instead",
    "commit_date": "2013-09-02T13:12:58+08:00",
    "metadata": {}
}
{
    "repo_name": "tornado",
    "new_commit_hash": "2d5f396407f9ce3c19751d1b6205a0f04143d3d6",
    "test_file_codes": [
        "from __future__ import absolute_import, division, print_function, with_statement\n\nimport collections\nfrom contextlib import closing\nimport errno\nimport gzip\nimport logging\nimport os\nimport re\nimport socket\nimport sys\n\nfrom tornado.httpclient import AsyncHTTPClient\nfrom tornado.httputil import HTTPHeaders\nfrom tornado.ioloop import IOLoop\nfrom tornado.log import gen_log\nfrom tornado.simple_httpclient import SimpleAsyncHTTPClient, _DEFAULT_CA_CERTS\nfrom tornado.test.httpclient_test import ChunkHandler, CountdownHandler, HelloWorldHandler\nfrom tornado.test import httpclient_test\nfrom tornado.testing import AsyncHTTPTestCase, AsyncHTTPSTestCase, AsyncTestCase, bind_unused_port, ExpectLog\nfrom tornado.test.util import unittest, skipOnTravis\nfrom tornado.web import RequestHandler, Application, asynchronous, url\n\n\nclass SimpleHTTPClientCommonTestCase(httpclient_test.HTTPClientCommonTestCase):\n    def get_http_client(self):\n        client = SimpleAsyncHTTPClient(io_loop=self.io_loop,\n                                       force_instance=True)\n        self.assertTrue(isinstance(client, SimpleAsyncHTTPClient))\n        return client\n\n\nclass TriggerHandler(RequestHandler):\n    def initialize(self, queue, wake_callback):\n        self.queue = queue\n        self.wake_callback = wake_callback\n\n    @asynchronous\n    def get(self):\n        logging.debug(\"queuing trigger\")\n        self.queue.append(self.finish)\n        if self.get_argument(\"wake\", \"true\") == \"true\":\n            self.wake_callback()\n\n\nclass HangHandler(RequestHandler):\n    @asynchronous\n    def get(self):\n        pass\n\n\nclass ContentLengthHandler(RequestHandler):\n    def get(self):\n        self.set_header(\"Content-Length\", self.get_argument(\"value\"))\n        self.write(\"ok\")\n\n\nclass HeadHandler(RequestHandler):\n    def head(self):\n        self.set_header(\"Content-Length\", \"7\")\n\n\nclass OptionsHandler(RequestHandler):\n    def options(self):\n        self.set_header(\"Access-Control-Allow-Origin\", \"*\")\n        self.write(\"ok\")\n\n\nclass NoContentHandler(RequestHandler):\n    def get(self):\n        if self.get_argument(\"error\", None):\n            self.set_header(\"Content-Length\", \"7\")\n        self.set_status(204)\n\n\nclass SeeOtherPostHandler(RequestHandler):\n    def post(self):\n        redirect_code = int(self.request.body)\n        assert redirect_code in (302, 303), \"unexpected body %r\" % self.request.body\n        self.set_header(\"Location\", \"/see_other_get\")\n        self.set_status(redirect_code)\n\n\nclass SeeOtherGetHandler(RequestHandler):\n    def get(self):\n        if self.request.body:\n            raise Exception(\"unexpected body %r\" % self.request.body)\n        self.write(\"ok\")\n\n\nclass HostEchoHandler(RequestHandler):\n    def get(self):\n        self.write(self.request.headers[\"Host\"])\n\n\nclass SimpleHTTPClientTestMixin(object):\n    def get_app(self):\n        # callable objects to finish pending /trigger requests\n        self.triggers = collections.deque()\n        return Application([\n            url(\"/trigger\", TriggerHandler, dict(queue=self.triggers,\n                                                 wake_callback=self.stop)),\n            url(\"/chunk\", ChunkHandler),\n            url(\"/countdown/([0-9]+)\", CountdownHandler, name=\"countdown\"),\n            url(\"/hang\", HangHandler),\n            url(\"/hello\", HelloWorldHandler),\n            url(\"/content_length\", ContentLengthHandler),\n            url(\"/head\", HeadHandler),\n            url(\"/options\", OptionsHandler),\n            url(\"/no_content\", NoContentHandler),\n            url(\"/see_other_post\", SeeOtherPostHandler),\n            url(\"/see_other_get\", SeeOtherGetHandler),\n            url(\"/host_echo\", HostEchoHandler),\n        ], gzip=True)\n\n    def test_singleton(self):\n        # Class \"constructor\" reuses objects on the same IOLoop\n        self.assertTrue(SimpleAsyncHTTPClient(self.io_loop) is\n                        SimpleAsyncHTTPClient(self.io_loop))\n        # unless force_instance is used\n        self.assertTrue(SimpleAsyncHTTPClient(self.io_loop) is not\n                        SimpleAsyncHTTPClient(self.io_loop,\n                                              force_instance=True))\n        # different IOLoops use different objects\n        io_loop2 = IOLoop()\n        self.assertTrue(SimpleAsyncHTTPClient(self.io_loop) is not\n                        SimpleAsyncHTTPClient(io_loop2))\n\n    def test_connection_limit(self):\n        with closing(self.create_client(max_clients=2)) as client:\n            self.assertEqual(client.max_clients, 2)\n            seen = []\n            # Send 4 requests.  Two can be sent immediately, while the others\n            # will be queued\n            for i in range(4):\n                client.fetch(self.get_url(\"/trigger\"),\n                             lambda response, i=i: (seen.append(i), self.stop()))\n            self.wait(condition=lambda: len(self.triggers) == 2)\n            self.assertEqual(len(client.queue), 2)\n\n            # Finish the first two requests and let the next two through\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: (len(self.triggers) == 2 and\n                                         len(seen) == 2))\n            self.assertEqual(set(seen), set([0, 1]))\n            self.assertEqual(len(client.queue), 0)\n\n            # Finish all the pending requests\n            self.triggers.popleft()()\n            self.triggers.popleft()()\n            self.wait(condition=lambda: len(seen) == 4)\n            self.assertEqual(set(seen), set([0, 1, 2, 3]))\n            self.assertEqual(len(self.triggers), 0)\n\n    def test_redirect_connection_limit(self):\n        # following redirects should not consume additional connections\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/countdown/3'), self.stop,\n                         max_redirects=3)\n            response = self.wait()\n            response.rethrow()\n\n    def test_default_certificates_exist(self):\n        open(_DEFAULT_CA_CERTS).close()\n\n    def test_gzip(self):\n        # All the tests in this file should be using gzip, but this test\n        # ensures that it is in fact getting compressed.\n        # Setting Accept-Encoding manually bypasses the client's\n        # decompression so we can see the raw data.\n        response = self.fetch(\"/chunk\", use_gzip=False,\n                              headers={\"Accept-Encoding\": \"gzip\"})\n        self.assertEqual(response.headers[\"Content-Encoding\"], \"gzip\")\n        self.assertNotEqual(response.body, b\"asdfqwer\")\n        # Our test data gets bigger when gzipped.  Oops.  :)\n        self.assertEqual(len(response.body), 34)\n        f = gzip.GzipFile(mode=\"r\", fileobj=response.buffer)\n        self.assertEqual(f.read(), b\"asdfqwer\")\n\n    def test_max_redirects(self):\n        response = self.fetch(\"/countdown/5\", max_redirects=3)\n        self.assertEqual(302, response.code)\n        # We requested 5, followed three redirects for 4, 3, 2, then the last\n        # unfollowed redirect is to 1.\n        self.assertTrue(response.request.url.endswith(\"/countdown/5\"))\n        self.assertTrue(response.effective_url.endswith(\"/countdown/2\"))\n        self.assertTrue(response.headers[\"Location\"].endswith(\"/countdown/1\"))\n\n    def test_header_reuse(self):\n        # Apps may reuse a headers object if they are only passing in constant\n        # headers like user-agent.  The header object should not be modified.\n        headers = HTTPHeaders({'User-Agent': 'Foo'})\n        self.fetch(\"/hello\", headers=headers)\n        self.assertEqual(list(headers.get_all()), [('User-Agent', 'Foo')])\n\n    def test_see_other_redirect(self):\n        for code in (302, 303):\n            response = self.fetch(\"/see_other_post\", method=\"POST\", body=\"%d\" % code)\n            self.assertEqual(200, response.code)\n            self.assertTrue(response.request.url.endswith(\"/see_other_post\"))\n            self.assertTrue(response.effective_url.endswith(\"/see_other_get\"))\n            # request is the original request, is a POST still\n            self.assertEqual(\"POST\", response.request.method)\n\n    @skipOnTravis\n    def test_request_timeout(self):\n        response = self.fetch('/trigger?wake=false', request_timeout=0.1)\n        self.assertEqual(response.code, 599)\n        self.assertTrue(0.099 < response.request_time < 0.15, response.request_time)\n        self.assertEqual(str(response.error), \"HTTP 599: Timeout\")\n        # trigger the hanging request to let it clean up after itself\n        self.triggers.popleft()()\n\n    @unittest.skipIf(not socket.has_ipv6, 'ipv6 support not present')\n    def test_ipv6(self):\n        try:\n            self.http_server.listen(self.get_http_port(), address='::1')\n        except socket.gaierror as e:\n            if e.args[0] == socket.EAI_ADDRFAMILY:\n                # python supports ipv6, but it's not configured on the network\n                # interface, so skip this test.\n                return\n            raise\n        url = self.get_url(\"/hello\").replace(\"localhost\", \"[::1]\")\n\n        # ipv6 is currently disabled by default and must be explicitly requested\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertEqual(response.code, 599)\n\n        self.http_client.fetch(url, self.stop, allow_ipv6=True)\n        response = self.wait()\n        self.assertEqual(response.body, b\"Hello world!\")\n\n    def test_multiple_content_length_accepted(self):\n        response = self.fetch(\"/content_length?value=2,2\")\n        self.assertEqual(response.body, b\"ok\")\n        response = self.fetch(\"/content_length?value=2,%202,2\")\n        self.assertEqual(response.body, b\"ok\")\n\n        response = self.fetch(\"/content_length?value=2,4\")\n        self.assertEqual(response.code, 599)\n        response = self.fetch(\"/content_length?value=2,%202,3\")\n        self.assertEqual(response.code, 599)\n\n    def test_head_request(self):\n        response = self.fetch(\"/head\", method=\"HEAD\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"7\")\n        self.assertFalse(response.body)\n\n    def test_options_request(self):\n        response = self.fetch(\"/options\", method=\"OPTIONS\")\n        self.assertEqual(response.code, 200)\n        self.assertEqual(response.headers[\"content-length\"], \"2\")\n        self.assertEqual(response.headers[\"access-control-allow-origin\"], \"*\")\n        self.assertEqual(response.body, b\"ok\")\n\n    def test_no_content(self):\n        response = self.fetch(\"/no_content\")\n        self.assertEqual(response.code, 204)\n        # 204 status doesn't need a content-length, but tornado will\n        # add a zero content-length anyway.\n        self.assertEqual(response.headers[\"Content-length\"], \"0\")\n\n        # 204 status with non-zero content length is malformed\n        response = self.fetch(\"/no_content?error=1\")\n        self.assertEqual(response.code, 599)\n\n    def test_host_header(self):\n        host_re = re.compile(b\"^localhost:[0-9]+$\")\n        response = self.fetch(\"/host_echo\")\n        self.assertTrue(host_re.match(response.body))\n\n        url = self.get_url(\"/host_echo\").replace(\"http://\", \"http://me:secret@\")\n        self.http_client.fetch(url, self.stop)\n        response = self.wait()\n        self.assertTrue(host_re.match(response.body), response.body)\n\n    def test_connection_refused(self):\n        server_socket, port = bind_unused_port()\n        server_socket.close()\n        with ExpectLog(gen_log, \".*\", required=False):\n            self.http_client.fetch(\"http://localhost:%d/\" % port, self.stop)\n            response = self.wait()\n        self.assertEqual(599, response.code)\n\n        if sys.platform != 'cygwin':\n            # cygwin returns EPERM instead of ECONNREFUSED here\n            self.assertTrue(str(errno.ECONNREFUSED) in str(response.error),\n                            response.error)\n            # This is usually \"Connection refused\".\n            # On windows, strerror is broken and returns \"Unknown error\".\n            expected_message = os.strerror(errno.ECONNREFUSED)\n            self.assertTrue(expected_message in str(response.error),\n                            response.error)\n\n\nclass SimpleHTTPClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPTestCase):\n    def setUp(self):\n        super(SimpleHTTPClientTestCase, self).setUp()\n        self.http_client = self.create_client()\n\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(self.io_loop, force_instance=True,\n                                     **kwargs)\n\n\nclass SimpleHTTPSClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPSTestCase):\n    def setUp(self):\n        super(SimpleHTTPSClientTestCase, self).setUp()\n        self.http_client = self.create_client()\n\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(self.io_loop, force_instance=True,\n                                     defaults=dict(validate_cert=False),\n                                     **kwargs)\n\n\nclass CreateAsyncHTTPClientTestCase(AsyncTestCase):\n    def setUp(self):\n        super(CreateAsyncHTTPClientTestCase, self).setUp()\n        self.saved = AsyncHTTPClient._save_configuration()\n\n    def tearDown(self):\n        AsyncHTTPClient._restore_configuration(self.saved)\n        super(CreateAsyncHTTPClientTestCase, self).tearDown()\n\n    def test_max_clients(self):\n        AsyncHTTPClient.configure(SimpleAsyncHTTPClient)\n        with closing(AsyncHTTPClient(\n                self.io_loop, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 10)\n        with closing(AsyncHTTPClient(\n                self.io_loop, max_clients=11, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 11)\n\n        # Now configure max_clients statically and try overriding it\n        # with each way max_clients can be passed\n        AsyncHTTPClient.configure(SimpleAsyncHTTPClient, max_clients=12)\n        with closing(AsyncHTTPClient(\n                self.io_loop, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 12)\n        with closing(AsyncHTTPClient(\n                self.io_loop, max_clients=13, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 13)\n        with closing(AsyncHTTPClient(\n                self.io_loop, max_clients=14, force_instance=True)) as client:\n            self.assertEqual(client.max_clients, 14)\n\n\nclass HTTP100ContinueTestCase(AsyncHTTPTestCase):\n    def respond_100(self, request):\n        self.request = request\n        self.request.connection.stream.write(\n            b\"HTTP/1.1 100 CONTINUE\\r\\n\\r\\n\",\n            self.respond_200)\n\n    def respond_200(self):\n        self.request.connection.stream.write(\n            b\"HTTP/1.1 200 OK\\r\\nContent-Length: 1\\r\\n\\r\\nA\",\n            self.request.connection.stream.close)\n\n    def get_app(self):\n        # Not a full Application, but works as an HTTPServer callback\n        return self.respond_100\n\n    def test_100_continue(self):\n        res = self.fetch('/')\n        self.assertEqual(res.body, b'A')\n\n\nclass HostnameMappingTestCase(AsyncHTTPTestCase):\n    def setUp(self):\n        super(HostnameMappingTestCase, self).setUp()\n        self.http_client = SimpleAsyncHTTPClient(\n            self.io_loop,\n            hostname_mapping={\n                'www.example.com': '127.0.0.1',\n                ('foo.example.com', 8000): ('127.0.0.1', self.get_http_port()),\n            })\n\n    def get_app(self):\n        return Application([url(\"/hello\", HelloWorldHandler), ])\n\n    def test_hostname_mapping(self):\n        self.http_client.fetch(\n            'http://www.example.com:%d/hello' % self.get_http_port(), self.stop)\n        response = self.wait()\n        response.rethrow()\n        self.assertEqual(response.body, b'Hello world!')\n\n    def test_port_mapping(self):\n        self.http_client.fetch('http://foo.example.com:8000/hello', self.stop)\n        response = self.wait()\n        response.rethrow()\n        self.assertEqual(response.body, b'Hello world!')\n\n\nclass HeavyloadAsyncHTTPClientTestCase(SimpleHTTPClientTestMixin, AsyncHTTPTestCase):\n    def create_client(self, **kwargs):\n        return SimpleAsyncHTTPClient(self.io_loop, force_instance=True, **kwargs)\n\n    def test_heavyload_timeout(self):\n        with closing(self.create_client(max_clients=1)) as client:\n            client.fetch(self.get_url('/trigger?wake=false'), self.stop, request_timeout=10)\n            client.fetch(self.get_url('/hello'), self.stop, connect_timeout=3)\n            response = self.wait()\n\n            self.assertEqual(response.code, 599)\n            self.assertTrue(2.9 < response.request_time < 3.1, response.request_time)\n            self.assertEqual(str(response.error), \"HTTP 599: Timeout\")\n            self.triggers.popleft()()\n\n\n",
        "#!/usr/bin/env python\nimport unittest\nimport sys\nimport time\nimport traceback\nimport platform\nimport os\n\n\nclass PytestLikeResult(unittest.TestResult):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.start_time = None\n        # Store (test, outcome, info) for each test:\n        #   outcome ∈ { \"passed\", \"failed\", \"error\", \"skipped\" }\n        #   info can hold the exception or skip reason, etc.\n        self.results = []\n\n    def startTestRun(self):\n        \"\"\"Called once before all tests.\"\"\"\n        self.start_time = time.time()\n        # Print a header similar to pytest\n        print(\"=\" * 29 + \" test session starts \" + \"=\" * 29)\n        # You can customize the platform/versions/paths as you like:\n        print(\n            f\"platform {platform.system().lower()} -- Python {platform.python_version()}\"\n        )\n        print(f\"rootdir: {os.path.abspath(os.curdir)}\")\n\n    def stopTestRun(self):\n        \"\"\"Called once after all tests are done.\"\"\"\n        elapsed = time.time() - self.start_time\n        print()  # blank line after final dot\n\n        # Summarize\n        ntests = len(self.results)\n        print(f\"collected {ntests} items\")\n\n        # Show details of failures/errors\n        failures = [r for r in self.results if r[1] == \"failed\"]\n        errors = [r for r in self.results if r[1] == \"error\"]\n\n        if failures:\n            print(\"\\n\" + \"=\" * 35 + \" FAILURES \" + \"=\" * 35)\n            for test, outcome, err_info in failures:\n                test = test.split(\"::\")\n                if len(test) == 3:\n                    test = f\"{test[1]}.{test[2]}\"\n                else:\n                    test = f\"{test[1]}\"\n                print(f\"__________ {test} __________\")\n                self._print_traceback(err_info)\n        if errors:\n            print(\"\\n\" + \"=\" * 35 + \" ERRORS \" + \"=\" * 37)\n            for test, outcome, err_info in errors:\n                test = test.split(\"::\")\n                if len(test) == 3:\n                    test = f\"{test[1]}.{test[2]}\"\n                else:\n                    test = f\"{test[1]}\"\n                print(f\"__________ {test} __________\")\n                self._print_traceback(err_info)\n\n        # Optional short summary lines for passes/fails/skips\n        print(\"\\n==================== short test summary info ====================\")\n        for test, outcome, info in self.results:\n            if outcome in (\"passed\", \"failed\", \"error\", \"skipped\"):\n                print(f\"{outcome.upper()} {test}\")\n\n        # Final one-line summary: “1 failed, 1 errors, 10 passed in 2.04s”\n        passed_count = sum(1 for r in self.results if r[1] == \"passed\")\n        failed_count = len(failures)\n        error_count = len(errors)\n        skipped_count = sum(1 for r in self.results if r[1] == \"skipped\")\n\n        summary_bits = []\n        if failed_count:\n            summary_bits.append(f\"{failed_count} failed\")\n        if error_count:\n            summary_bits.append(f\"{error_count} error{'s' if error_count != 1 else ''}\")\n        if passed_count:\n            summary_bits.append(f\"{passed_count} passed\")\n        if skipped_count:\n            summary_bits.append(f\"{skipped_count} skipped\")\n\n        summary_str = \", \".join(summary_bits) if summary_bits else \"no tests run\"\n        print(\n            f\"=================== {summary_str} in {elapsed:.2f}s ===================\"\n        )\n\n    def startTest(self, test):\n        \"\"\"Called right before each test method.\"\"\"\n        super().startTest(test)\n        # Print a dot or some indicator\n        print(\".\", end=\"\", flush=True)\n\n    def addSuccess(self, test):\n        super().addSuccess(test)\n        self.results.append((self._test_id(test), \"passed\", None))\n\n    def addFailure(self, test, err):\n        super().addFailure(test, err)\n        self.results.append((self._test_id(test), \"failed\", err))\n\n    def addError(self, test, err):\n        super().addError(test, err)\n        self.results.append((self._test_id(test), \"error\", err))\n\n    def addSkip(self, test, reason):\n        super().addSkip(test, reason)\n        self.results.append((self._test_id(test), \"skipped\", reason))\n\n    def _print_traceback(self, err_info):\n        \"\"\"Helper to print the traceback like pytest does.\"\"\"\n        if isinstance(err_info, tuple) and len(err_info) == 3:\n            exc_type, exc_value, tb = err_info\n            traceback.print_exception(exc_type, exc_value, tb, file=sys.stdout)\n        else:\n            print(str(err_info))\n\n    def _test_id(self, test):\n        try:\n            return f\"{test.__class__.__module__}::{test.__class__.__name__}::{test._testMethodName}\"\n        except AttributeError:\n            # Fallback for _ErrorHolder objects\n            return f\"{test.__class__.__module__}::{test.__class__.__name__}\"\n\n\nclass PytestLikeRunner(unittest.TextTestRunner):\n    \"\"\"A custom TextTestRunner that uses the PytestLikeResult.\"\"\"\n\n    resultclass = PytestLikeResult\n\n    def run(self, test):\n        result = self._makeResult()\n        # Overriding run to ensure we call startTestRun/stopTestRun\n        result.startTestRun()\n        test(result)\n        result.stopTestRun()\n        return result\n\n    def tearDown(self):\n        # Reset signal handlers\n        from twisted.internet import reactor\n\n        reactor.removeAll()\n        reactor.stop()\n        super().tearDown()\n\n\ndef main():\n    loader = unittest.TestLoader()\n    suite = loader.discover(\".\", pattern=\"test_*.py\")  # discover tests in r2e_tests/\n    runner = PytestLikeRunner(verbosity=0)\n    result = runner.run(suite)\n    # Exit with code 0 if all tests passed/skipped, 1 if there were fails/errors\n    sys.exit(not result.wasSuccessful())\n\n\nif __name__ == \"__main__\":\n    main()\n"
    ],
    "test_file_names": [
        "test_1.py",
        "tornado_unittest_runner.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "",
    "setup_res_stderr": "Using CPython 3.9.21\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 1 package in 694ms\nPrepared 1 package in 844ms\nInstalled 1 package in 0.79ms\n + tornado==3.2.dev1 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6)\nResolved 29 packages in 111ms\nInstalled 29 packages in 74ms\n + attrs==24.3.0\n + automat==24.8.1\n + cachetools==5.5.0\n + cffi==1.17.1\n + chardet==5.2.0\n + colorama==0.4.6\n + constantly==23.10.4\n + distlib==0.3.9\n + exceptiongroup==1.2.2\n + filelock==3.16.1\n + hyperlink==21.0.0\n + idna==3.10\n + incremental==24.7.2\n + iniconfig==2.0.0\n + packaging==24.2\n + platformdirs==4.3.6\n + pluggy==1.5.0\n + pycares==4.5.0\n + pycparser==2.22\n + pycurl==7.45.4\n + pyproject-api==1.8.0\n + pytest==8.3.4\n + setuptools==75.6.0\n + tomli==2.2.1\n + tox==4.23.2\n + twisted==24.11.0\n + typing-extensions==4.12.2\n + virtualenv==20.28.0\n + zope-interface==7.2\n",
    "new_commit_res_code": 1,
    "new_commit_res_stdout": "============================= test session starts =============================\nplatform linux -- Python 3.9.21\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6\n...........................................................................\ncollected 75 items\n\n=================================== ERRORS =====================================\n__________ SimpleHTTPSClientTestCase.test_connection_limit __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 138, in test_connection_limit\n    self.wait(condition=lambda: len(self.triggers) == 2)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_gzip __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 172, in test_gzip\n    response = self.fetch(\"/chunk\", use_gzip=False,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_head_request __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 248, in test_head_request\n    response = self.fetch(\"/head\", method=\"HEAD\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_header_reuse __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 194, in test_header_reuse\n    self.fetch(\"/hello\", headers=headers)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_host_header __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 273, in test_host_header\n    response = self.fetch(\"/host_echo\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_ipv6 __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 233, in test_ipv6\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_max_redirects __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 182, in test_max_redirects\n    response = self.fetch(\"/countdown/5\", max_redirects=3)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_multiple_content_length_accepted __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 237, in test_multiple_content_length_accepted\n    response = self.fetch(\"/content_length?value=2,2\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_no_content __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 261, in test_no_content\n    response = self.fetch(\"/no_content\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_options_request __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 254, in test_options_request\n    response = self.fetch(\"/options\", method=\"OPTIONS\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_redirect_connection_limit __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 161, in test_redirect_connection_limit\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_request_timeout __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 208, in test_request_timeout\n    response = self.fetch('/trigger?wake=false', request_timeout=0.1)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_see_other_redirect __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 199, in test_see_other_redirect\n    response = self.fetch(\"/see_other_post\", method=\"POST\", body=\"%d\" % code)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n\n==================== short test summary info ====================\nPASSED r2e_tests.test_1::CreateAsyncHTTPClientTestCase::test_max_clients\nPASSED r2e_tests.test_1::HTTP100ContinueTestCase::test_100_continue\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_connection_limit\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_connection_refused\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_default_certificates_exist\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_gzip\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_head_request\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_header_reuse\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_heavyload_timeout\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_host_header\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_ipv6\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_max_redirects\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_multiple_content_length_accepted\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_no_content\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_options_request\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_redirect_connection_limit\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_request_timeout\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_see_other_redirect\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_singleton\nPASSED r2e_tests.test_1::HostnameMappingTestCase::test_hostname_mapping\nPASSED r2e_tests.test_1::HostnameMappingTestCase::test_port_mapping\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_304_with_content_length\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_all_methods\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_basic_auth\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_basic_auth_explicit_mode\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_body_encoding\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_chunked\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_chunked_close\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_configure_defaults\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_credentials_in_url\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_final_callback_stack_context\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_follow_redirect\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_future_http_error\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_future_interface\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_header_callback\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_header_callback_stack_context\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_hello_world\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_post\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_reuse_request_from_response\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_streaming_callback\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_streaming_stack_context\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_types\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_unsupported_auth_mode\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_connection_limit\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_connection_refused\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_default_certificates_exist\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_gzip\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_head_request\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_header_reuse\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_host_header\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_ipv6\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_max_redirects\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_multiple_content_length_accepted\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_no_content\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_options_request\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_redirect_connection_limit\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_request_timeout\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_see_other_redirect\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_singleton\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_connection_limit\nPASSED r2e_tests.test_1::SimpleHTTPSClientTestCase::test_connection_refused\nPASSED r2e_tests.test_1::SimpleHTTPSClientTestCase::test_default_certificates_exist\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_gzip\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_head_request\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_header_reuse\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_host_header\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_ipv6\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_max_redirects\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_multiple_content_length_accepted\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_no_content\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_options_request\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_redirect_connection_limit\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_request_timeout\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_see_other_redirect\nPASSED r2e_tests.test_1::SimpleHTTPSClientTestCase::test_singleton\n=================== 13 errors, 62 passed in 3.59s ===================\n",
    "new_commit_res_stderr": "WARNING:tornado.access:405 HEAD /all_methods (127.0.0.1) 0.19ms\nWARNING:tornado.access:404 GET /notfound (127.0.0.1) 0.21ms\n",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts =============================\nplatform linux -- Python 3.9.21\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6\n...........................................................................\ncollected 75 items\n\n=================================== FAILURES ===================================\n__________ HeavyloadAsyncHTTPClientTestCase.test_heavyload_timeout __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 409, in test_heavyload_timeout\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 251, in timeout_func\n    raise self.failureException(\nAssertionError: Async operation timed out after 5 seconds\n\n=================================== ERRORS =====================================\n__________ SimpleHTTPSClientTestCase.test_connection_limit __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 138, in test_connection_limit\n    self.wait(condition=lambda: len(self.triggers) == 2)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_gzip __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 172, in test_gzip\n    response = self.fetch(\"/chunk\", use_gzip=False,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_head_request __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 248, in test_head_request\n    response = self.fetch(\"/head\", method=\"HEAD\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_header_reuse __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 194, in test_header_reuse\n    self.fetch(\"/hello\", headers=headers)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_host_header __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 273, in test_host_header\n    response = self.fetch(\"/host_echo\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_ipv6 __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 233, in test_ipv6\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_max_redirects __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 182, in test_max_redirects\n    response = self.fetch(\"/countdown/5\", max_redirects=3)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_multiple_content_length_accepted __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 237, in test_multiple_content_length_accepted\n    response = self.fetch(\"/content_length?value=2,2\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_no_content __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 261, in test_no_content\n    response = self.fetch(\"/no_content\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_options_request __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 254, in test_options_request\n    response = self.fetch(\"/options\", method=\"OPTIONS\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_redirect_connection_limit __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 161, in test_redirect_connection_limit\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_request_timeout __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 208, in test_request_timeout\n    response = self.fetch('/trigger?wake=false', request_timeout=0.1)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n__________ SimpleHTTPSClientTestCase.test_see_other_redirect __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/r2e_tests/test_1.py\", line 199, in test_see_other_redirect\n    response = self.fetch(\"/see_other_post\", method=\"POST\", body=\"%d\" % code)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 330, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 269, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/testing.py\", line 205, in __rethrow\n    raise_exc_info(failure)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/stack_context.py\", line 302, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 153, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/tcpserver.py\", line 213, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 378, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_2d5f396407f9ce3c19751d1b6205a0f04143d3d6/tornado/netutil.py\", line 359, in ssl_options_to_context\n    context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))\nssl.SSLError: [SSL: EE_KEY_TOO_SMALL] ee key too small (_ssl.c:4062)\n\n==================== short test summary info ====================\nPASSED r2e_tests.test_1::CreateAsyncHTTPClientTestCase::test_max_clients\nPASSED r2e_tests.test_1::HTTP100ContinueTestCase::test_100_continue\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_connection_limit\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_connection_refused\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_default_certificates_exist\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_gzip\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_head_request\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_header_reuse\nFAILED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_heavyload_timeout\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_host_header\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_ipv6\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_max_redirects\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_multiple_content_length_accepted\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_no_content\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_options_request\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_redirect_connection_limit\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_request_timeout\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_see_other_redirect\nPASSED r2e_tests.test_1::HeavyloadAsyncHTTPClientTestCase::test_singleton\nPASSED r2e_tests.test_1::HostnameMappingTestCase::test_hostname_mapping\nPASSED r2e_tests.test_1::HostnameMappingTestCase::test_port_mapping\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_304_with_content_length\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_all_methods\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_basic_auth\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_basic_auth_explicit_mode\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_body_encoding\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_chunked\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_chunked_close\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_configure_defaults\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_credentials_in_url\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_final_callback_stack_context\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_follow_redirect\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_future_http_error\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_future_interface\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_header_callback\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_header_callback_stack_context\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_hello_world\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_post\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_reuse_request_from_response\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_streaming_callback\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_streaming_stack_context\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_types\nPASSED r2e_tests.test_1::SimpleHTTPClientCommonTestCase::test_unsupported_auth_mode\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_connection_limit\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_connection_refused\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_default_certificates_exist\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_gzip\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_head_request\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_header_reuse\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_host_header\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_ipv6\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_max_redirects\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_multiple_content_length_accepted\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_no_content\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_options_request\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_redirect_connection_limit\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_request_timeout\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_see_other_redirect\nPASSED r2e_tests.test_1::SimpleHTTPClientTestCase::test_singleton\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_connection_limit\nPASSED r2e_tests.test_1::SimpleHTTPSClientTestCase::test_connection_refused\nPASSED r2e_tests.test_1::SimpleHTTPSClientTestCase::test_default_certificates_exist\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_gzip\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_head_request\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_header_reuse\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_host_header\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_ipv6\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_max_redirects\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_multiple_content_length_accepted\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_no_content\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_options_request\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_redirect_connection_limit\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_request_timeout\nERROR r2e_tests.test_1::SimpleHTTPSClientTestCase::test_see_other_redirect\nPASSED r2e_tests.test_1::SimpleHTTPSClientTestCase::test_singleton\n=================== 1 failed, 13 errors, 61 passed in 5.59s ===================\n",
    "old_commit_res_stderr": "WARNING:tornado.access:405 HEAD /all_methods (127.0.0.1) 0.18ms\nWARNING:tornado.access:404 GET /notfound (127.0.0.1) 0.19ms\n"
}
tornado/httpclient.py tornado/simple_httpclient.py tornado/test/simple_httpclient_test.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** Heavy Load Timeout Fails Due to Incorrect Timeout Handling

**Description:**
When performing a heavy load test with multiple concurrent HTTP requests, the client experiences unexpected timeout behavior. Specifically, initiating multiple fetch operations with both `request_timeout` and `async_timeout` results in operations timing out after a longer duration than intended, causing timeout errors.

**Example Code:**
```python
def test_heavyload_timeout(self):
    client = create_client(max_clients=1)
    client.fetch("http://example.com/trigger?wake=false", self.stop, request_timeout=10)
    client.fetch("http://example.com/hello", self.stop, async_timeout=3)
    response = self.wait()
```

**Expected Behavior:**
Both fetch operations should respect their respective timeout settings (`request_timeout=10` seconds and `async_timeout=3` seconds). The second fetch should timeout after approximately 3 seconds if the request does not complete, allowing the heavy load test to handle timeouts correctly.

**Actual Behavior:**
The second fetch operation does not timeout at the specified 3 seconds. Instead, it results in a timeout error after 5 seconds, which is longer than intended and causes the test to fail unexpectedly.

**Error Message:**
```
AssertionError: Async operation timed out after 5 seconds
```
[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### tornado/simple_httpclient.py
#!/usr/bin/env python
from __future__ import absolute_import, division, print_function, with_statement

from tornado.escape import utf8, _unicode, native_str
from tornado.httpclient import HTTPResponse, HTTPError, AsyncHTTPClient, main, _RequestProxy
from tornado.httputil import HTTPHeaders
from tornado.iostream import IOStream, SSLIOStream
from tornado.netutil import Resolver, OverrideResolver
from tornado.log import gen_log
from tornado import stack_context
from tornado.util import GzipDecompressor

import base64
import collections
import copy
import functools
import os.path
import re
import socket
import ssl
import sys

try:
    from io import BytesIO  # python 3
except ImportError:
    from cStringIO import StringIO as BytesIO  # python 2

try:
    import urlparse  # py2
except ImportError:
    import urllib.parse as urlparse  # py3

_DEFAULT_CA_CERTS = os.path.dirname(__file__) + '/ca-certificates.crt'


class SimpleAsyncHTTPClient(AsyncHTTPClient):
    """Non-blocking HTTP client with no external dependencies.

    This class implements an HTTP 1.1 client on top of Tornado's IOStreams.
    It does not currently implement all applicable parts of the HTTP
    specification, but it does enough to work with major web service APIs.

    Some features found in the curl-based AsyncHTTPClient are not yet
    supported.  In particular, proxies are not supported, connections
    are not reused, and callers cannot select the network interface to be
    used.
    """
    def initialize(self, io_loop, max_clients=10,
                   hostname_mapping=None, max_buffer_size=104857600,
                   resolver=None, defaults=None):
        """Creates a AsyncHTTPClient.

        Only a single AsyncHTTPClient instance exists per IOLoop
        in order to provide limitations on the number of pending connections.
        force_instance=True may be used to suppress this behavior.

        max_clients is the number of concurrent requests that can be
        in progress.  Note that this arguments are only used when the
        client is first created, and will be ignored when an existing
        client is reused.

        hostname_mapping is a dictionary mapping hostnames to IP addresses.
        It can be used to make local DNS changes when modifying system-wide
        settings like /etc/hosts is not possible or desirable (e.g. in
        unittests).

        max_buffer_size is the number of bytes that can be read by IOStream. It
        defaults to 100mb.
        """
        super(SimpleAsyncHTTPClient, self).initialize(io_loop,
                                                      defaults=defaults)
        self.max_clients = max_clients
        self.queue = collections.deque()
        self.active = {}
        self.waiting = {}
        self.max_buffer_size = max_buffer_size
        if resolver:
            self.resolver = resolver
            self.own_resolver = False
        else:
            self.resolver = Resolver(io_loop=io_loop)
            self.own_resolver = True
        if hostname_mapping is not None:
            self.resolver = OverrideResolver(resolver=self.resolver,
                                             mapping=hostname_mapping)

    def close(self):
        super(SimpleAsyncHTTPClient, self).close()
        if self.own_resolver:
            self.resolver.close()

    def fetch_impl(self, request, callback):
        key = object()
        self.queue.append((key, request, callback))
        if not len(self.active) < self.max_clients:
            timeout_handle = self.io_loop.add_timeout(
                    request.start_time + request.async_timeout,
                    functools.partial(self._on_timeout, key))
            self.waiting[key] = (request, callback, timeout_handle)
        self._process_queue()
        if self.queue:
            gen_log.debug("max_clients limit reached, request queued. "
                          "%d active, %d queued requests." % (
                              len(self.active), len(self.queue)))

    def _process_queue(self):
        with stack_context.NullContext():
            while self.queue and len(self.active) < self.max_clients:
                key, request, callback = self.queue.popleft()
                self._remove_timeout(key)
                self.active[key] = (request, callback)
                release_callback = functools.partial(self._release_fetch, key)
                self._handle_request(request, release_callback, callback)

    def _handle_request(self, request, release_callback, final_callback):
        _HTTPConnection(self.io_loop, self, request, release_callback,
                        final_callback, self.max_buffer_size, self.resolver)

    def _release_fetch(self, key):
        del self.active[key]
        self._process_queue()

    def _remove_timeout(self, key):
        if key in self.waiting:
            request, callback, timeout_handle = self.waiting[key]
            self.io_loop.remove_timeout(timeout_handle)
            del self.waiting[key]

    def _on_timeout(self, key):
        request, callback, timeout_handle = self.waiting[key]
        self.queue.remove((key, request, callback))
        timeout_response = HTTPResponse(
                request, 599, error=HTTPError(599, "Timeout"),
                request_time=self.io_loop.time() - request.start_time)
        self.io_loop.add_callback(callback, timeout_response)
        del self.waiting[key]


class _HTTPConnection(object):
    _SUPPORTED_METHODS = set(["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"])

    def __init__(self, io_loop, client, request, release_callback,
                 final_callback, max_buffer_size, resolver):
        self.start_time = io_loop.time()
        self.io_loop = io_loop
        self.client = client
        self.request = request
        self.release_callback = release_callback
        self.final_callback = final_callback
        self.max_buffer_size = max_buffer_size
        self.resolver = resolver
        self.code = None
        self.headers = None
        self.chunks = None
        self._decompressor = None
        # Timeout handle returned by IOLoop.add_timeout
        self._timeout = None
        with stack_context.ExceptionStackContext(self._handle_exception):
            self.parsed = urlparse.urlsplit(_unicode(self.request.url))
            if self.parsed.scheme not in ("http", "https"):
                raise ValueError("Unsupported url scheme: %s" %
                                 self.request.url)
            # urlsplit results have hostname and port results, but they
            # didn't support ipv6 literals until python 2.7.
            netloc = self.parsed.netloc
            if "@" in netloc:
                userpass, _, netloc = netloc.rpartition("@")
            match = re.match(r'^(.+):(\d+)$', netloc)
            if match:
                host = match.group(1)
                port = int(match.group(2))
            else:
                host = netloc
                port = 443 if self.parsed.scheme == "https" else 80
            if re.match(r'^\[.*\]$', host):
                # raw ipv6 addresses in urls are enclosed in brackets
                host = host[1:-1]
            self.parsed_hostname = host  # save final host for _on_connect

            if request.allow_ipv6:
                af = socket.AF_UNSPEC
            else:
                # We only try the first IP we get from getaddrinfo,
                # so restrict to ipv4 by default.
                af = socket.AF_INET

            self.resolver.resolve(host, port, af, callback=self._on_resolve)

    def _on_resolve(self, addrinfo):
        self.stream = self._create_stream(addrinfo)
        timeout = min(self.request.connect_timeout, self.request.request_timeout)
        if timeout:
            self._timeout = self.io_loop.add_timeout(
                self.start_time + timeout,
                stack_context.wrap(self._on_timeout))
        self.stream.set_close_callback(self._on_close)
        # ipv6 addresses are broken (in self.parsed.hostname) until
        # 2.7, here is correctly parsed value calculated in __init__
        sockaddr = addrinfo[0][1]
        self.stream.connect(sockaddr, self._on_connect,
                            server_hostname=self.parsed_hostname)

    def _create_stream(self, addrinfo):
        af = addrinfo[0][0]
        if self.parsed.scheme == "https":
            ssl_options = {}
            if self.request.validate_cert:
                ssl_options["cert_reqs"] = ssl.CERT_REQUIRED
            if self.request.ca_certs is not None:
                ssl_options["ca_certs"] = self.request.ca_certs
            else:
                ssl_options["ca_certs"] = _DEFAULT_CA_CERTS
            if self.request.client_key is not None:
                ssl_options["keyfile"] = self.request.client_key
            if self.request.client_cert is not None:
                ssl_options["certfile"] = self.request.client_cert

            # SSL interoperability is tricky.  We want to disable
            # SSLv2 for security reasons; it wasn't disabled by default
            # until openssl 1.0.  The best way to do this is to use
            # the SSL_OP_NO_SSLv2, but that wasn't exposed to python
            # until 3.2.  Python 2.7 adds the ciphers argument, which
            # can also be used to disable SSLv2.  As a last resort
            # on python 2.6, we set ssl_version to SSLv3.  This is
            # more narrow than we'd like since it also breaks
            # compatibility with servers configured for TLSv1 only,
            # but nearly all servers support SSLv3:
            # http://blog.ivanristic.com/2011/09/ssl-survey-protocol-support.html
            if sys.version_info >= (2, 7):
                ssl_options["ciphers"] = "DEFAULT:!SSLv2"
            else:
                # This is really only necessary for pre-1.0 versions
                # of openssl, but python 2.6 doesn't expose version
                # information.
                ssl_options["ssl_version"] = ssl.PROTOCOL_SSLv3

            return SSLIOStream(socket.socket(af),
                               io_loop=self.io_loop,
                               ssl_options=ssl_options,
                               max_buffer_size=self.max_buffer_size)
        else:
            return IOStream(socket.socket(af),
                            io_loop=self.io_loop,
                            max_buffer_size=self.max_buffer_size)

    def _on_timeout(self):
        self._timeout = None
        if self.final_callback is not None:
            raise HTTPError(599, "Timeout")

    def _remove_timeout(self):
        if self._timeout is not None:
            self.io_loop.remove_timeout(self._timeout)
            self._timeout = None

    def _on_connect(self):
        self._remove_timeout()
        if self.request.request_timeout:
            self._timeout = self.io_loop.add_timeout(
                self.start_time + self.request.request_timeout,
                stack_context.wrap(self._on_timeout))
        if (self.request.method not in self._SUPPORTED_METHODS and
                not self.request.allow_nonstandard_methods):
            raise KeyError("unknown method %s" % self.request.method)
        for key in ('network_interface',
                    'proxy_host', 'proxy_port',
                    'proxy_username', 'proxy_password'):
            if getattr(self.request, key, None):
                raise NotImplementedError('%s not supported' % key)
        if "Connection" not in self.request.headers:
            self.request.headers["Connection"] = "close"
        if "Host" not in self.request.headers:
            if '@' in self.parsed.netloc:
                self.request.headers["Host"] = self.parsed.netloc.rpartition('@')[-1]
            else:
                self.request.headers["Host"] = self.parsed.netloc
        username, password = None, None
        if self.parsed.username is not None:
            username, password = self.parsed.username, self.parsed.password
        elif self.request.auth_username is not None:
            username = self.request.auth_username
            password = self.request.auth_password or ''
        if username is not None:
            if self.request.auth_mode not in (None, "basic"):
                raise ValueError("unsupported auth_mode %s",
                                 self.request.auth_mode)
            auth = utf8(username) + b":" + utf8(password)
            self.request.headers["Authorization"] = (b"Basic " +
                                                     base64.b64encode(auth))
        if self.request.user_agent:
            self.request.headers["User-Agent"] = self.request.user_agent
        if not self.request.allow_nonstandard_methods:
            if self.request.method in ("POST", "PATCH", "PUT"):
                assert self.request.body is not None
            else:
                assert self.request.body is None
        if self.request.body is not None:
            self.request.headers["Content-Length"] = str(len(
                self.request.body))
        if (self.request.method == "POST" and
                "Content-Type" not in self.request.headers):
            self.request.headers["Content-Type"] = "application/x-www-form-urlencoded"
        if self.request.use_gzip:
            self.request.headers["Accept-Encoding"] = "gzip"
        req_path = ((self.parsed.path or '/') +
                   (('?' + self.parsed.query) if self.parsed.query else ''))
        request_lines = [utf8("%s %s HTTP/1.1" % (self.request.method,
                                                  req_path))]
        for k, v in self.request.headers.get_all():
            line = utf8(k) + b": " + utf8(v)
            if b'\n' in line:
                raise ValueError('Newline in header: ' + repr(line))
            request_lines.append(line)
        request_str = b"\r\n".join(request_lines) + b"\r\n\r\n"
        if self.request.body is not None:
            request_str += self.request.body
        self.stream.set_nodelay(True)
        self.stream.write(request_str)
        self.stream.read_until_regex(b"\r?\n\r?\n", self._on_headers)

    def _release(self):
        if self.release_callback is not None:
            release_callback = self.release_callback
            self.release_callback = None
            release_callback()

    def _run_callback(self, response):
        self._release()
        if self.final_callback is not None:
            final_callback = self.final_callback
            self.final_callback = None
            self.io_loop.add_callback(final_callback, response)

    def _handle_exception(self, typ, value, tb):
        if self.final_callback:
            self._remove_timeout()
            self._run_callback(HTTPResponse(self.request, 599, error=value,
                                            request_time=self.io_loop.time() - self.start_time,
                                            ))

            if hasattr(self, "stream"):
                self.stream.close()
            return True
        else:
            # If our callback has already been called, we are probably
            # catching an exception that is not caused by us but rather
            # some child of our callback. Rather than drop it on the floor,
            # pass it along.
            return False

    def _on_close(self):
        if self.final_callback is not None:
            message = "Connection closed"
            if self.stream.error:
                message = str(self.stream.error)
            raise HTTPError(599, message)

    def _handle_1xx(self, code):
        self.stream.read_until_regex(b"\r?\n\r?\n", self._on_headers)

    def _on_headers(self, data):
        data = native_str(data.decode("latin1"))
        first_line, _, header_data = data.partition("\n")
        match = re.match("HTTP/1.[01] ([0-9]+) ([^\r]*)", first_line)
        assert match
        code = int(match.group(1))
        self.headers = HTTPHeaders.parse(header_data)
        if 100 <= code < 200:
            self._handle_1xx(code)
            return
        else:
            self.code = code
            self.reason = match.group(2)

        if "Content-Length" in self.headers:
            if "," in self.headers["Content-Length"]:
                # Proxies sometimes cause Content-Length headers to get
                # duplicated.  If all the values are identical then we can
                # use them but if they differ it's an error.
                pieces = re.split(r',\s*', self.headers["Content-Length"])
                if any(i != pieces[0] for i in pieces):
                    raise ValueError("Multiple unequal Content-Lengths: %r" %
                                     self.headers["Content-Length"])
                self.headers["Content-Length"] = pieces[0]
            content_length = int(self.headers["Content-Length"])
        else:
            content_length = None

        if self.request.header_callback is not None:
            # re-attach the newline we split on earlier
            self.request.header_callback(first_line + _)
            for k, v in self.headers.get_all():
                self.request.header_callback("%s: %s\r\n" % (k, v))
            self.request.header_callback('\r\n')

        if self.request.method == "HEAD" or self.code == 304:
            # HEAD requests and 304 responses never have content, even
            # though they may have content-length headers
            self._on_body(b"")
            return
        if 100 <= self.code < 200 or self.code == 204:
            # These response codes never have bodies
            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3
            if ("Transfer-Encoding" in self.headers or
                    content_length not in (None, 0)):
                raise ValueError("Response with code %d should not have body" %
                                 self.code)
            self._on_body(b"")
            return

        if (self.request.use_gzip and
                self.headers.get("Content-Encoding") == "gzip"):
            self._decompressor = GzipDecompressor()
        if self.headers.get("Transfer-Encoding") == "chunked":
            self.chunks = []
            self.stream.read_until(b"\r\n", self._on_chunk_length)
        elif content_length is not None:
            self.stream.read_bytes(content_length, self._on_body)
        else:
            self.stream.read_until_close(self._on_body)

    def _on_body(self, data):
        self._remove_timeout()
        original_request = getattr(self.request, "original_request",
                                   self.request)
        if (self.request.follow_redirects and
            self.request.max_redirects > 0 and
                self.code in (301, 302, 303, 307)):
            assert isinstance(self.request, _RequestProxy)
            new_request = copy.copy(self.request.request)
            new_request.url = urlparse.urljoin(self.request.url,
                                               self.headers["Location"])
            new_request.max_redirects = self.request.max_redirects - 1
            del new_request.headers["Host"]
            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4
            # Client SHOULD make a GET request after a 303.
            # According to the spec, 302 should be followed by the same
            # method as the original request, but in practice browsers
            # treat 302 the same as 303, and many servers use 302 for
            # compatibility with pre-HTTP/1.1 user agents which don't
            # understand the 303 status.
            if self.code in (302, 303):
                new_request.method = "GET"
                new_request.body = None
                for h in ["Content-Length", "Content-Type",
                          "Content-Encoding", "Transfer-Encoding"]:
                    try:
                        del self.request.headers[h]
                    except KeyError:
                        pass
            new_request.original_request = original_request
            final_callback = self.final_callback
            self.final_callback = None
            self._release()
            self.client.fetch(new_request, final_callback)
            self._on_end_request()
            return
        if self._decompressor:
            data = (self._decompressor.decompress(data) +
                    self._decompressor.flush())
        if self.request.streaming_callback:
            if self.chunks is None:
                # if chunks is not None, we already called streaming_callback
                # in _on_chunk_data
                self.request.streaming_callback(data)
            buffer = BytesIO()
        else:
            buffer = BytesIO(data)  # TODO: don't require one big string?
        response = HTTPResponse(original_request,
                                self.code, reason=self.reason,
                                headers=self.headers,
                                request_time=self.io_loop.time() - self.start_time,
                                buffer=buffer,
                                effective_url=self.request.url)
        self._run_callback(response)
        self._on_end_request()

    def _on_end_request(self):
        self.stream.close()

    def _on_chunk_length(self, data):
        # TODO: "chunk extensions" http://tools.ietf.org/html/rfc2616#section-3.6.1
        length = int(data.strip(), 16)
        if length == 0:
            if self._decompressor is not None:
                tail = self._decompressor.flush()
                if tail:
                    # I believe the tail will always be empty (i.e.
                    # decompress will return all it can).  The purpose
                    # of the flush call is to detect errors such
                    # as truncated input.  But in case it ever returns
                    # anything, treat it as an extra chunk
                    if self.request.streaming_callback is not None:
                        self.request.streaming_callback(tail)
                    else:
                        self.chunks.append(tail)
                # all the data has been decompressed, so we don't need to
                # decompress again in _on_body
                self._decompressor = None
            self._on_body(b''.join(self.chunks))
        else:
            self.stream.read_bytes(length + 2,  # chunk ends with \r\n
                                   self._on_chunk_data)

    def _on_chunk_data(self, data):
        assert data[-2:] == b"\r\n"
        chunk = data[:-2]
        if self._decompressor:
            chunk = self._decompressor.decompress(chunk)
        if self.request.streaming_callback is not None:
            self.request.streaming_callback(chunk)
        else:
            self.chunks.append(chunk)
        self.stream.read_until(b"\r\n", self._on_chunk_length)


if __name__ == "__main__":
    AsyncHTTPClient.configure(SimpleAsyncHTTPClient)
    main()

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
[ISSUE]
**Title:** Heavy Load Timeout Fails Due to Incorrect Timeout Handling

**Description:**
When performing a heavy load test with multiple concurrent HTTP requests, the client experiences unexpected timeout behavior. Specifically, initiating multiple fetch operations with both `request_timeout` and `async_timeout` results in operations timing out after a longer duration than intended, causing timeout errors.

**Example Code:**
```python
def test_heavyload_timeout(self):
    client = create_client(max_clients=1)
    client.fetch("http://example.com/trigger?wake=false", self.stop, request_timeout=10)
    client.fetch("http://example.com/hello", self.stop, async_timeout=3)
    response = self.wait()
```

**Expected Behavior:**
Both fetch operations should respect their respective timeout settings (`request_timeout=10` seconds and `async_timeout=3` seconds). The second fetch should timeout after approximately 3 seconds if the request does not complete, allowing the heavy load test to handle timeouts correctly.

**Actual Behavior:**
The second fetch operation does not timeout at the specified 3 seconds. Instead, it results in a timeout error after 5 seconds, which is longer than intended and causes the test to fail unexpectedly.

**Error Message:**
```
AssertionError: Async operation timed out after 5 seconds
```
[/ISSUE]
{
    "CreateAsyncHTTPClientTestCase.test_max_clients": "PASSED",
    "HTTP100ContinueTestCase.test_100_continue": "PASSED",
    "HeavyloadAsyncHTTPClientTestCase.test_connection_limit": "PASSED",
    "HeavyloadAsyncHTTPClientTestCase.test_connection_refused": "PASSED",
    "HeavyloadAsyncHTTPClientTestCase.test_default_certificates_exist": "PASSED",
    "HeavyloadAsyncHTTPClientTestCase.test_gzip": "PASSED",
    "HeavyloadAsyncHTTPClientTestCase.test_head_request": "PASSED",
    "HeavyloadAsyncHTTPClientTestCase.test_header_reuse": "PASSED",
    "HeavyloadAsyncHTTPClientTestCase.test_heavyload_timeout": "PASSED",
    "HeavyloadAsyncHTTPClientTestCase.test_host_header": "PASSED",
    "HeavyloadAsyncHTTPClientTestCase.test_ipv6": "PASSED",
    "HeavyloadAsyncHTTPClientTestCase.test_max_redirects": "PASSED",
    "HeavyloadAsyncHTTPClientTestCase.test_multiple_content_length_accepted": "PASSED",
    "HeavyloadAsyncHTTPClientTestCase.test_no_content": "PASSED",
    "HeavyloadAsyncHTTPClientTestCase.test_options_request": "PASSED",
    "HeavyloadAsyncHTTPClientTestCase.test_redirect_connection_limit": "PASSED",
    "HeavyloadAsyncHTTPClientTestCase.test_request_timeout": "PASSED",
    "HeavyloadAsyncHTTPClientTestCase.test_see_other_redirect": "PASSED",
    "HeavyloadAsyncHTTPClientTestCase.test_singleton": "PASSED",
    "HostnameMappingTestCase.test_hostname_mapping": "PASSED",
    "HostnameMappingTestCase.test_port_mapping": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_304_with_content_length": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_all_methods": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_basic_auth": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_basic_auth_explicit_mode": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_body_encoding": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_chunked": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_chunked_close": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_configure_defaults": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_credentials_in_url": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_final_callback_stack_context": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_follow_redirect": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_future_http_error": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_future_interface": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_header_callback": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_header_callback_stack_context": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_hello_world": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_post": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_reuse_request_from_response": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_streaming_callback": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_streaming_stack_context": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_types": "PASSED",
    "SimpleHTTPClientCommonTestCase.test_unsupported_auth_mode": "PASSED",
    "SimpleHTTPClientTestCase.test_connection_limit": "PASSED",
    "SimpleHTTPClientTestCase.test_connection_refused": "PASSED",
    "SimpleHTTPClientTestCase.test_default_certificates_exist": "PASSED",
    "SimpleHTTPClientTestCase.test_gzip": "PASSED",
    "SimpleHTTPClientTestCase.test_head_request": "PASSED",
    "SimpleHTTPClientTestCase.test_header_reuse": "PASSED",
    "SimpleHTTPClientTestCase.test_host_header": "PASSED",
    "SimpleHTTPClientTestCase.test_ipv6": "PASSED",
    "SimpleHTTPClientTestCase.test_max_redirects": "PASSED",
    "SimpleHTTPClientTestCase.test_multiple_content_length_accepted": "PASSED",
    "SimpleHTTPClientTestCase.test_no_content": "PASSED",
    "SimpleHTTPClientTestCase.test_options_request": "PASSED",
    "SimpleHTTPClientTestCase.test_redirect_connection_limit": "PASSED",
    "SimpleHTTPClientTestCase.test_request_timeout": "PASSED",
    "SimpleHTTPClientTestCase.test_see_other_redirect": "PASSED",
    "SimpleHTTPClientTestCase.test_singleton": "PASSED",
    "SimpleHTTPSClientTestCase.test_connection_limit": "ERROR",
    "SimpleHTTPSClientTestCase.test_connection_refused": "PASSED",
    "SimpleHTTPSClientTestCase.test_default_certificates_exist": "PASSED",
    "SimpleHTTPSClientTestCase.test_gzip": "ERROR",
    "SimpleHTTPSClientTestCase.test_head_request": "ERROR",
    "SimpleHTTPSClientTestCase.test_header_reuse": "ERROR",
    "SimpleHTTPSClientTestCase.test_host_header": "ERROR",
    "SimpleHTTPSClientTestCase.test_ipv6": "ERROR",
    "SimpleHTTPSClientTestCase.test_max_redirects": "ERROR",
    "SimpleHTTPSClientTestCase.test_multiple_content_length_accepted": "ERROR",
    "SimpleHTTPSClientTestCase.test_no_content": "ERROR",
    "SimpleHTTPSClientTestCase.test_options_request": "ERROR",
    "SimpleHTTPSClientTestCase.test_redirect_connection_limit": "ERROR",
    "SimpleHTTPSClientTestCase.test_request_timeout": "ERROR",
    "SimpleHTTPSClientTestCase.test_see_other_redirect": "ERROR",
    "SimpleHTTPSClientTestCase.test_singleton": "PASSED"
}
diff --git a/tornado/httpclient.py b/tornado/httpclient.py
index 91dc2db8..67675894 100644
--- a/tornado/httpclient.py
+++ b/tornado/httpclient.py
@@ -241,7 +241,6 @@ class HTTPRequest(object):
     _DEFAULTS = dict(
         connect_timeout=20.0,
         request_timeout=20.0,
-        async_timeout=20.0,
         follow_redirects=True,
         max_redirects=5,
         use_gzip=True,
@@ -252,7 +251,6 @@ class HTTPRequest(object):
     def __init__(self, url, method="GET", headers=None, body=None,
                  auth_username=None, auth_password=None, auth_mode=None,
                  connect_timeout=None, request_timeout=None,
-                 async_timeout=None,
                  if_modified_since=None, follow_redirects=None,
                  max_redirects=None, user_agent=None, use_gzip=None,
                  network_interface=None, streaming_callback=None,
@@ -342,7 +340,6 @@ class HTTPRequest(object):
         self.auth_mode = auth_mode
         self.connect_timeout = connect_timeout
         self.request_timeout = request_timeout
-        self.async_timeout = async_timeout
         self.follow_redirects = follow_redirects
         self.max_redirects = max_redirects
         self.user_agent = user_agent
diff --git a/tornado/simple_httpclient.py b/tornado/simple_httpclient.py
index 75cb9ff7..eb241122 100644
--- a/tornado/simple_httpclient.py
+++ b/tornado/simple_httpclient.py
@@ -94,7 +94,7 @@ class SimpleAsyncHTTPClient(AsyncHTTPClient):
         self.queue.append((key, request, callback))
         if not len(self.active) < self.max_clients:
             timeout_handle = self.io_loop.add_timeout(
-                    request.start_time + request.async_timeout,
+                    request.start_time + min(request.connect_timeout, request.request_timeout),
                     functools.partial(self._on_timeout, key))
             self.waiting[key] = (request, callback, timeout_handle)
         self._process_queue()

{"tornado/simple_httpclient.py": "#!/usr/bin/env python\nfrom __future__ import absolute_import, division, print_function, with_statement\n\nfrom tornado.escape import utf8, _unicode, native_str\nfrom tornado.httpclient import HTTPResponse, HTTPError, AsyncHTTPClient, main, _RequestProxy\nfrom tornado.httputil import HTTPHeaders\nfrom tornado.iostream import IOStream, SSLIOStream\nfrom tornado.netutil import Resolver, OverrideResolver\nfrom tornado.log import gen_log\nfrom tornado import stack_context\nfrom tornado.util import GzipDecompressor\n\nimport base64\nimport collections\nimport copy\nimport functools\nimport os.path\nimport re\nimport socket\nimport ssl\nimport sys\n\ntry:\n    from io import BytesIO  # python 3\nexcept ImportError:\n    from cStringIO import StringIO as BytesIO  # python 2\n\ntry:\n    import urlparse  # py2\nexcept ImportError:\n    import urllib.parse as urlparse  # py3\n\n_DEFAULT_CA_CERTS = os.path.dirname(__file__) + '/ca-certificates.crt'\n\n\nclass SimpleAsyncHTTPClient(AsyncHTTPClient):\n    \"\"\"Non-blocking HTTP client with no external dependencies.\n\n    This class implements an HTTP 1.1 client on top of Tornado's IOStreams.\n    It does not currently implement all applicable parts of the HTTP\n    specification, but it does enough to work with major web service APIs.\n\n    Some features found in the curl-based AsyncHTTPClient are not yet\n    supported.  In particular, proxies are not supported, connections\n    are not reused, and callers cannot select the network interface to be\n    used.\n    \"\"\"\n    def initialize(self, io_loop, max_clients=10,\n                   hostname_mapping=None, max_buffer_size=104857600,\n                   resolver=None, defaults=None):\n        \"\"\"Creates a AsyncHTTPClient.\n\n        Only a single AsyncHTTPClient instance exists per IOLoop\n        in order to provide limitations on the number of pending connections.\n        force_instance=True may be used to suppress this behavior.\n\n        max_clients is the number of concurrent requests that can be\n        in progress.  Note that this arguments are only used when the\n        client is first created, and will be ignored when an existing\n        client is reused.\n\n        hostname_mapping is a dictionary mapping hostnames to IP addresses.\n        It can be used to make local DNS changes when modifying system-wide\n        settings like /etc/hosts is not possible or desirable (e.g. in\n        unittests).\n\n        max_buffer_size is the number of bytes that can be read by IOStream. It\n        defaults to 100mb.\n        \"\"\"\n        super(SimpleAsyncHTTPClient, self).initialize(io_loop,\n                                                      defaults=defaults)\n        self.max_clients = max_clients\n        self.queue = collections.deque()\n        self.active = {}\n        self.waiting = {}\n        self.max_buffer_size = max_buffer_size\n        if resolver:\n            self.resolver = resolver\n            self.own_resolver = False\n        else:\n            self.resolver = Resolver(io_loop=io_loop)\n            self.own_resolver = True\n        if hostname_mapping is not None:\n            self.resolver = OverrideResolver(resolver=self.resolver,\n                                             mapping=hostname_mapping)\n\n    def close(self):\n        super(SimpleAsyncHTTPClient, self).close()\n        if self.own_resolver:\n            self.resolver.close()\n\n    def fetch_impl(self, request, callback):\n        key = object()\n        self.queue.append((key, request, callback))\n        if not len(self.active) < self.max_clients:\n            timeout_handle = self.io_loop.add_timeout(\n                    request.start_time + request.async_timeout,\n                    functools.partial(self._on_timeout, key))\n            self.waiting[key] = (request, callback, timeout_handle)\n        self._process_queue()\n        if self.queue:\n            gen_log.debug(\"max_clients limit reached, request queued. \"\n                          \"%d active, %d queued requests.\" % (\n                              len(self.active), len(self.queue)))\n\n    def _process_queue(self):\n        with stack_context.NullContext():\n            while self.queue and len(self.active) < self.max_clients:\n                key, request, callback = self.queue.popleft()\n                self._remove_timeout(key)\n                self.active[key] = (request, callback)\n                release_callback = functools.partial(self._release_fetch, key)\n                self._handle_request(request, release_callback, callback)\n\n    def _handle_request(self, request, release_callback, final_callback):\n        _HTTPConnection(self.io_loop, self, request, release_callback,\n                        final_callback, self.max_buffer_size, self.resolver)\n\n    def _release_fetch(self, key):\n        del self.active[key]\n        self._process_queue()\n\n    def _remove_timeout(self, key):\n        if key in self.waiting:\n            request, callback, timeout_handle = self.waiting[key]\n            self.io_loop.remove_timeout(timeout_handle)\n            del self.waiting[key]\n\n    def _on_timeout(self, key):\n        request, callback, timeout_handle = self.waiting[key]\n        self.queue.remove((key, request, callback))\n        timeout_response = HTTPResponse(\n                request, 599, error=HTTPError(599, \"Timeout\"),\n                request_time=self.io_loop.time() - request.start_time)\n        self.io_loop.add_callback(callback, timeout_response)\n        del self.waiting[key]\n\n\nclass _HTTPConnection(object):\n    _SUPPORTED_METHODS = set([\"GET\", \"HEAD\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\", \"OPTIONS\"])\n\n    def __init__(self, io_loop, client, request, release_callback,\n                 final_callback, max_buffer_size, resolver):\n        self.start_time = io_loop.time()\n        self.io_loop = io_loop\n        self.client = client\n        self.request = request\n        self.release_callback = release_callback\n        self.final_callback = final_callback\n        self.max_buffer_size = max_buffer_size\n        self.resolver = resolver\n        self.code = None\n        self.headers = None\n        self.chunks = None\n        self._decompressor = None\n        # Timeout handle returned by IOLoop.add_timeout\n        self._timeout = None\n        with stack_context.ExceptionStackContext(self._handle_exception):\n            self.parsed = urlparse.urlsplit(_unicode(self.request.url))\n            if self.parsed.scheme not in (\"http\", \"https\"):\n                raise ValueError(\"Unsupported url scheme: %s\" %\n                                 self.request.url)\n            # urlsplit results have hostname and port results, but they\n            # didn't support ipv6 literals until python 2.7.\n            netloc = self.parsed.netloc\n            if \"@\" in netloc:\n                userpass, _, netloc = netloc.rpartition(\"@\")\n            match = re.match(r'^(.+):(\\d+)$', netloc)\n            if match:\n                host = match.group(1)\n                port = int(match.group(2))\n            else:\n                host = netloc\n                port = 443 if self.parsed.scheme == \"https\" else 80\n            if re.match(r'^\\[.*\\]$', host):\n                # raw ipv6 addresses in urls are enclosed in brackets\n                host = host[1:-1]\n            self.parsed_hostname = host  # save final host for _on_connect\n\n            if request.allow_ipv6:\n                af = socket.AF_UNSPEC\n            else:\n                # We only try the first IP we get from getaddrinfo,\n                # so restrict to ipv4 by default.\n                af = socket.AF_INET\n\n            self.resolver.resolve(host, port, af, callback=self._on_resolve)\n\n    def _on_resolve(self, addrinfo):\n        self.stream = self._create_stream(addrinfo)\n        timeout = min(self.request.connect_timeout, self.request.request_timeout)\n        if timeout:\n            self._timeout = self.io_loop.add_timeout(\n                self.start_time + timeout,\n                stack_context.wrap(self._on_timeout))\n        self.stream.set_close_callback(self._on_close)\n        # ipv6 addresses are broken (in self.parsed.hostname) until\n        # 2.7, here is correctly parsed value calculated in __init__\n        sockaddr = addrinfo[0][1]\n        self.stream.connect(sockaddr, self._on_connect,\n                            server_hostname=self.parsed_hostname)\n\n    def _create_stream(self, addrinfo):\n        af = addrinfo[0][0]\n        if self.parsed.scheme == \"https\":\n            ssl_options = {}\n            if self.request.validate_cert:\n                ssl_options[\"cert_reqs\"] = ssl.CERT_REQUIRED\n            if self.request.ca_certs is not None:\n                ssl_options[\"ca_certs\"] = self.request.ca_certs\n            else:\n                ssl_options[\"ca_certs\"] = _DEFAULT_CA_CERTS\n            if self.request.client_key is not None:\n                ssl_options[\"keyfile\"] = self.request.client_key\n            if self.request.client_cert is not None:\n                ssl_options[\"certfile\"] = self.request.client_cert\n\n            # SSL interoperability is tricky.  We want to disable\n            # SSLv2 for security reasons; it wasn't disabled by default\n            # until openssl 1.0.  The best way to do this is to use\n            # the SSL_OP_NO_SSLv2, but that wasn't exposed to python\n            # until 3.2.  Python 2.7 adds the ciphers argument, which\n            # can also be used to disable SSLv2.  As a last resort\n            # on python 2.6, we set ssl_version to SSLv3.  This is\n            # more narrow than we'd like since it also breaks\n            # compatibility with servers configured for TLSv1 only,\n            # but nearly all servers support SSLv3:\n            # http://blog.ivanristic.com/2011/09/ssl-survey-protocol-support.html\n            if sys.version_info >= (2, 7):\n                ssl_options[\"ciphers\"] = \"DEFAULT:!SSLv2\"\n            else:\n                # This is really only necessary for pre-1.0 versions\n                # of openssl, but python 2.6 doesn't expose version\n                # information.\n                ssl_options[\"ssl_version\"] = ssl.PROTOCOL_SSLv3\n\n            return SSLIOStream(socket.socket(af),\n                               io_loop=self.io_loop,\n                               ssl_options=ssl_options,\n                               max_buffer_size=self.max_buffer_size)\n        else:\n            return IOStream(socket.socket(af),\n                            io_loop=self.io_loop,\n                            max_buffer_size=self.max_buffer_size)\n\n    def _on_timeout(self):\n        self._timeout = None\n        if self.final_callback is not None:\n            raise HTTPError(599, \"Timeout\")\n\n    def _remove_timeout(self):\n        if self._timeout is not None:\n            self.io_loop.remove_timeout(self._timeout)\n            self._timeout = None\n\n    def _on_connect(self):\n        self._remove_timeout()\n        if self.request.request_timeout:\n            self._timeout = self.io_loop.add_timeout(\n                self.start_time + self.request.request_timeout,\n                stack_context.wrap(self._on_timeout))\n        if (self.request.method not in self._SUPPORTED_METHODS and\n                not self.request.allow_nonstandard_methods):\n            raise KeyError(\"unknown method %s\" % self.request.method)\n        for key in ('network_interface',\n                    'proxy_host', 'proxy_port',\n                    'proxy_username', 'proxy_password'):\n            if getattr(self.request, key, None):\n                raise NotImplementedError('%s not supported' % key)\n        if \"Connection\" not in self.request.headers:\n            self.request.headers[\"Connection\"] = \"close\"\n        if \"Host\" not in self.request.headers:\n            if '@' in self.parsed.netloc:\n                self.request.headers[\"Host\"] = self.parsed.netloc.rpartition('@')[-1]\n            else:\n                self.request.headers[\"Host\"] = self.parsed.netloc\n        username, password = None, None\n        if self.parsed.username is not None:\n            username, password = self.parsed.username, self.parsed.password\n        elif self.request.auth_username is not None:\n            username = self.request.auth_username\n            password = self.request.auth_password or ''\n        if username is not None:\n            if self.request.auth_mode not in (None, \"basic\"):\n                raise ValueError(\"unsupported auth_mode %s\",\n                                 self.request.auth_mode)\n            auth = utf8(username) + b\":\" + utf8(password)\n            self.request.headers[\"Authorization\"] = (b\"Basic \" +\n                                                     base64.b64encode(auth))\n        if self.request.user_agent:\n            self.request.headers[\"User-Agent\"] = self.request.user_agent\n        if not self.request.allow_nonstandard_methods:\n            if self.request.method in (\"POST\", \"PATCH\", \"PUT\"):\n                assert self.request.body is not None\n            else:\n                assert self.request.body is None\n        if self.request.body is not None:\n            self.request.headers[\"Content-Length\"] = str(len(\n                self.request.body))\n        if (self.request.method == \"POST\" and\n                \"Content-Type\" not in self.request.headers):\n            self.request.headers[\"Content-Type\"] = \"application/x-www-form-urlencoded\"\n        if self.request.use_gzip:\n            self.request.headers[\"Accept-Encoding\"] = \"gzip\"\n        req_path = ((self.parsed.path or '/') +\n                   (('?' + self.parsed.query) if self.parsed.query else ''))\n        request_lines = [utf8(\"%s %s HTTP/1.1\" % (self.request.method,\n                                                  req_path))]\n        for k, v in self.request.headers.get_all():\n            line = utf8(k) + b\": \" + utf8(v)\n            if b'\\n' in line:\n                raise ValueError('Newline in header: ' + repr(line))\n            request_lines.append(line)\n        request_str = b\"\\r\\n\".join(request_lines) + b\"\\r\\n\\r\\n\"\n        if self.request.body is not None:\n            request_str += self.request.body\n        self.stream.set_nodelay(True)\n        self.stream.write(request_str)\n        self.stream.read_until_regex(b\"\\r?\\n\\r?\\n\", self._on_headers)\n\n    def _release(self):\n        if self.release_callback is not None:\n            release_callback = self.release_callback\n            self.release_callback = None\n            release_callback()\n\n    def _run_callback(self, response):\n        self._release()\n        if self.final_callback is not None:\n            final_callback = self.final_callback\n            self.final_callback = None\n            self.io_loop.add_callback(final_callback, response)\n\n    def _handle_exception(self, typ, value, tb):\n        if self.final_callback:\n            self._remove_timeout()\n            self._run_callback(HTTPResponse(self.request, 599, error=value,\n                                            request_time=self.io_loop.time() - self.start_time,\n                                            ))\n\n            if hasattr(self, \"stream\"):\n                self.stream.close()\n            return True\n        else:\n            # If our callback has already been called, we are probably\n            # catching an exception that is not caused by us but rather\n            # some child of our callback. Rather than drop it on the floor,\n            # pass it along.\n            return False\n\n    def _on_close(self):\n        if self.final_callback is not None:\n            message = \"Connection closed\"\n            if self.stream.error:\n                message = str(self.stream.error)\n            raise HTTPError(599, message)\n\n    def _handle_1xx(self, code):\n        self.stream.read_until_regex(b\"\\r?\\n\\r?\\n\", self._on_headers)\n\n    def _on_headers(self, data):\n        data = native_str(data.decode(\"latin1\"))\n        first_line, _, header_data = data.partition(\"\\n\")\n        match = re.match(\"HTTP/1.[01] ([0-9]+) ([^\\r]*)\", first_line)\n        assert match\n        code = int(match.group(1))\n        self.headers = HTTPHeaders.parse(header_data)\n        if 100 <= code < 200:\n            self._handle_1xx(code)\n            return\n        else:\n            self.code = code\n            self.reason = match.group(2)\n\n        if \"Content-Length\" in self.headers:\n            if \",\" in self.headers[\"Content-Length\"]:\n                # Proxies sometimes cause Content-Length headers to get\n                # duplicated.  If all the values are identical then we can\n                # use them but if they differ it's an error.\n                pieces = re.split(r',\\s*', self.headers[\"Content-Length\"])\n                if any(i != pieces[0] for i in pieces):\n                    raise ValueError(\"Multiple unequal Content-Lengths: %r\" %\n                                     self.headers[\"Content-Length\"])\n                self.headers[\"Content-Length\"] = pieces[0]\n            content_length = int(self.headers[\"Content-Length\"])\n        else:\n            content_length = None\n\n        if self.request.header_callback is not None:\n            # re-attach the newline we split on earlier\n            self.request.header_callback(first_line + _)\n            for k, v in self.headers.get_all():\n                self.request.header_callback(\"%s: %s\\r\\n\" % (k, v))\n            self.request.header_callback('\\r\\n')\n\n        if self.request.method == \"HEAD\" or self.code == 304:\n            # HEAD requests and 304 responses never have content, even\n            # though they may have content-length headers\n            self._on_body(b\"\")\n            return\n        if 100 <= self.code < 200 or self.code == 204:\n            # These response codes never have bodies\n            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3\n            if (\"Transfer-Encoding\" in self.headers or\n                    content_length not in (None, 0)):\n                raise ValueError(\"Response with code %d should not have body\" %\n                                 self.code)\n            self._on_body(b\"\")\n            return\n\n        if (self.request.use_gzip and\n                self.headers.get(\"Content-Encoding\") == \"gzip\"):\n            self._decompressor = GzipDecompressor()\n        if self.headers.get(\"Transfer-Encoding\") == \"chunked\":\n            self.chunks = []\n            self.stream.read_until(b\"\\r\\n\", self._on_chunk_length)\n        elif content_length is not None:\n            self.stream.read_bytes(content_length, self._on_body)\n        else:\n            self.stream.read_until_close(self._on_body)\n\n    def _on_body(self, data):\n        self._remove_timeout()\n        original_request = getattr(self.request, \"original_request\",\n                                   self.request)\n        if (self.request.follow_redirects and\n            self.request.max_redirects > 0 and\n                self.code in (301, 302, 303, 307)):\n            assert isinstance(self.request, _RequestProxy)\n            new_request = copy.copy(self.request.request)\n            new_request.url = urlparse.urljoin(self.request.url,\n                                               self.headers[\"Location\"])\n            new_request.max_redirects = self.request.max_redirects - 1\n            del new_request.headers[\"Host\"]\n            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4\n            # Client SHOULD make a GET request after a 303.\n            # According to the spec, 302 should be followed by the same\n            # method as the original request, but in practice browsers\n            # treat 302 the same as 303, and many servers use 302 for\n            # compatibility with pre-HTTP/1.1 user agents which don't\n            # understand the 303 status.\n            if self.code in (302, 303):\n                new_request.method = \"GET\"\n                new_request.body = None\n                for h in [\"Content-Length\", \"Content-Type\",\n                          \"Content-Encoding\", \"Transfer-Encoding\"]:\n                    try:\n                        del self.request.headers[h]\n                    except KeyError:\n                        pass\n            new_request.original_request = original_request\n            final_callback = self.final_callback\n            self.final_callback = None\n            self._release()\n            self.client.fetch(new_request, final_callback)\n            self._on_end_request()\n            return\n        if self._decompressor:\n            data = (self._decompressor.decompress(data) +\n                    self._decompressor.flush())\n        if self.request.streaming_callback:\n            if self.chunks is None:\n                # if chunks is not None, we already called streaming_callback\n                # in _on_chunk_data\n                self.request.streaming_callback(data)\n            buffer = BytesIO()\n        else:\n            buffer = BytesIO(data)  # TODO: don't require one big string?\n        response = HTTPResponse(original_request,\n                                self.code, reason=self.reason,\n                                headers=self.headers,\n                                request_time=self.io_loop.time() - self.start_time,\n                                buffer=buffer,\n                                effective_url=self.request.url)\n        self._run_callback(response)\n        self._on_end_request()\n\n    def _on_end_request(self):\n        self.stream.close()\n\n    def _on_chunk_length(self, data):\n        # TODO: \"chunk extensions\" http://tools.ietf.org/html/rfc2616#section-3.6.1\n        length = int(data.strip(), 16)\n        if length == 0:\n            if self._decompressor is not None:\n                tail = self._decompressor.flush()\n                if tail:\n                    # I believe the tail will always be empty (i.e.\n                    # decompress will return all it can).  The purpose\n                    # of the flush call is to detect errors such\n                    # as truncated input.  But in case it ever returns\n                    # anything, treat it as an extra chunk\n                    if self.request.streaming_callback is not None:\n                        self.request.streaming_callback(tail)\n                    else:\n                        self.chunks.append(tail)\n                # all the data has been decompressed, so we don't need to\n                # decompress again in _on_body\n                self._decompressor = None\n            self._on_body(b''.join(self.chunks))\n        else:\n            self.stream.read_bytes(length + 2,  # chunk ends with \\r\\n\n                                   self._on_chunk_data)\n\n    def _on_chunk_data(self, data):\n        assert data[-2:] == b\"\\r\\n\"\n        chunk = data[:-2]\n        if self._decompressor:\n            chunk = self._decompressor.decompress(chunk)\n        if self.request.streaming_callback is not None:\n            self.request.streaming_callback(chunk)\n        else:\n            self.chunks.append(chunk)\n        self.stream.read_until(b\"\\r\\n\", self._on_chunk_length)\n\n\nif __name__ == \"__main__\":\n    AsyncHTTPClient.configure(SimpleAsyncHTTPClient)\n    main()\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

Your response format must follow the template below:
<think>
Your thoughts or/and draft, like working through an exercise on scratch paper. Be as casual and as long as you want until you are confident to generate a correct solution.
</think>
<solution>
Final solution presented to the user.
</solution>
system
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** Heavy Load Timeout Fails Due to Incorrect Timeout Handling

**Description:**
When performing a heavy load test with multiple concurrent HTTP requests, the client experiences unexpected timeout behavior. Specifically, initiating multiple fetch operations with both `request_timeout` and `async_timeout` results in operations timing out after a longer duration than intended, causing timeout errors.

**Example Code:**
```python
def test_heavyload_timeout(self):
    client = create_client(max_clients=1)
    client.fetch("http://example.com/trigger?wake=false", self.stop, request_timeout=10)
    client.fetch("http://example.com/hello", self.stop, async_timeout=3)
    response = self.wait()
```

**Expected Behavior:**
Both fetch operations should respect their respective timeout settings (`request_timeout=10` seconds and `async_timeout=3` seconds). The second fetch should timeout after approximately 3 seconds if the request does not complete, allowing the heavy load test to handle timeouts correctly.

**Actual Behavior:**
The second fetch operation does not timeout at the specified 3 seconds. Instead, it results in a timeout error after 5 seconds, which is longer than intended and causes the test to fail unexpectedly.

**Error Message:**
```
AssertionError: Async operation timed out after 5 seconds
```
[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### tornado/simple_httpclient.py
#!/usr/bin/env python
from __future__ import absolute_import, division, print_function, with_statement

from tornado.escape import utf8, _unicode, native_str
from tornado.httpclient import HTTPResponse, HTTPError, AsyncHTTPClient, main, _RequestProxy
from tornado.httputil import HTTPHeaders
from tornado.iostream import IOStream, SSLIOStream
from tornado.netutil import Resolver, OverrideResolver
from tornado.log import gen_log
from tornado import stack_context
from tornado.util import GzipDecompressor

import base64
import collections
import copy
import functools
import os.path
import re
import socket
import ssl
import sys

try:
    from io import BytesIO  # python 3
except ImportError:
    from cStringIO import StringIO as BytesIO  # python 2

try:
    import urlparse  # py2
except ImportError:
    import urllib.parse as urlparse  # py3

_DEFAULT_CA_CERTS = os.path.dirname(__file__) + '/ca-certificates.crt'


class SimpleAsyncHTTPClient(AsyncHTTPClient):
    """Non-blocking HTTP client with no external dependencies.

    This class implements an HTTP 1.1 client on top of Tornado's IOStreams.
    It does not currently implement all applicable parts of the HTTP
    specification, but it does enough to work with major web service APIs.

    Some features found in the curl-based AsyncHTTPClient are not yet
    supported.  In particular, proxies are not supported, connections
    are not reused, and callers cannot select the network interface to be
    used.
    """
    def initialize(self, io_loop, max_clients=10,
                   hostname_mapping=None, max_buffer_size=104857600,
                   resolver=None, defaults=None):
        """Creates a AsyncHTTPClient.

        Only a single AsyncHTTPClient instance exists per IOLoop
        in order to provide limitations on the number of pending connections.
        force_instance=True may be used to suppress this behavior.

        max_clients is the number of concurrent requests that can be
        in progress.  Note that this arguments are only used when the
        client is first created, and will be ignored when an existing
        client is reused.

        hostname_mapping is a dictionary mapping hostnames to IP addresses.
        It can be used to make local DNS changes when modifying system-wide
        settings like /etc/hosts is not possible or desirable (e.g. in
        unittests).

        max_buffer_size is the number of bytes that can be read by IOStream. It
        defaults to 100mb.
        """
        super(SimpleAsyncHTTPClient, self).initialize(io_loop,
                                                      defaults=defaults)
        self.max_clients = max_clients
        self.queue = collections.deque()
        self.active = {}
        self.waiting = {}
        self.max_buffer_size = max_buffer_size
        if resolver:
            self.resolver = resolver
            self.own_resolver = False
        else:
            self.resolver = Resolver(io_loop=io_loop)
            self.own_resolver = True
        if hostname_mapping is not None:
            self.resolver = OverrideResolver(resolver=self.resolver,
                                             mapping=hostname_mapping)

    def close(self):
        super(SimpleAsyncHTTPClient, self).close()
        if self.own_resolver:
            self.resolver.close()

    def fetch_impl(self, request, callback):
        key = object()
        self.queue.append((key, request, callback))
        if not len(self.active) < self.max_clients:
            timeout_handle = self.io_loop.add_timeout(
                    request.start_time + request.async_timeout,
                    functools.partial(self._on_timeout, key))
            self.waiting[key] = (request, callback, timeout_handle)
        self._process_queue()
        if self.queue:
            gen_log.debug("max_clients limit reached, request queued. "
                          "%d active, %d queued requests." % (
                              len(self.active), len(self.queue)))

    def _process_queue(self):
        with stack_context.NullContext():
            while self.queue and len(self.active) < self.max_clients:
                key, request, callback = self.queue.popleft()
                self._remove_timeout(key)
                self.active[key] = (request, callback)
                release_callback = functools.partial(self._release_fetch, key)
                self._handle_request(request, release_callback, callback)

    def _handle_request(self, request, release_callback, final_callback):
        _HTTPConnection(self.io_loop, self, request, release_callback,
                        final_callback, self.max_buffer_size, self.resolver)

    def _release_fetch(self, key):
        del self.active[key]
        self._process_queue()

    def _remove_timeout(self, key):
        if key in self.waiting:
            request, callback, timeout_handle = self.waiting[key]
            self.io_loop.remove_timeout(timeout_handle)
            del self.waiting[key]

    def _on_timeout(self, key):
        request, callback, timeout_handle = self.waiting[key]
        self.queue.remove((key, request, callback))
        timeout_response = HTTPResponse(
                request, 599, error=HTTPError(599, "Timeout"),
                request_time=self.io_loop.time() - request.start_time)
        self.io_loop.add_callback(callback, timeout_response)
        del self.waiting[key]


class _HTTPConnection(object):
    _SUPPORTED_METHODS = set(["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"])

    def __init__(self, io_loop, client, request, release_callback,
                 final_callback, max_buffer_size, resolver):
        self.start_time = io_loop.time()
        self.io_loop = io_loop
        self.client = client
        self.request = request
        self.release_callback = release_callback
        self.final_callback = final_callback
        self.max_buffer_size = max_buffer_size
        self.resolver = resolver
        self.code = None
        self.headers = None
        self.chunks = None
        self._decompressor = None
        # Timeout handle returned by IOLoop.add_timeout
        self._timeout = None
        with stack_context.ExceptionStackContext(self._handle_exception):
            self.parsed = urlparse.urlsplit(_unicode(self.request.url))
            if self.parsed.scheme not in ("http", "https"):
                raise ValueError("Unsupported url scheme: %s" %
                                 self.request.url)
            # urlsplit results have hostname and port results, but they
            # didn't support ipv6 literals until python 2.7.
            netloc = self.parsed.netloc
            if "@" in netloc:
                userpass, _, netloc = netloc.rpartition("@")
            match = re.match(r'^(.+):(\d+)$', netloc)
            if match:
                host = match.group(1)
                port = int(match.group(2))
            else:
                host = netloc
                port = 443 if self.parsed.scheme == "https" else 80
            if re.match(r'^\[.*\]$', host):
                # raw ipv6 addresses in urls are enclosed in brackets
                host = host[1:-1]
            self.parsed_hostname = host  # save final host for _on_connect

            if request.allow_ipv6:
                af = socket.AF_UNSPEC
            else:
                # We only try the first IP we get from getaddrinfo,
                # so restrict to ipv4 by default.
                af = socket.AF_INET

            self.resolver.resolve(host, port, af, callback=self._on_resolve)

    def _on_resolve(self, addrinfo):
        self.stream = self._create_stream(addrinfo)
        timeout = min(self.request.connect_timeout, self.request.request_timeout)
        if timeout:
            self._timeout = self.io_loop.add_timeout(
                self.start_time + timeout,
                stack_context.wrap(self._on_timeout))
        self.stream.set_close_callback(self._on_close)
        # ipv6 addresses are broken (in self.parsed.hostname) until
        # 2.7, here is correctly parsed value calculated in __init__
        sockaddr = addrinfo[0][1]
        self.stream.connect(sockaddr, self._on_connect,
                            server_hostname=self.parsed_hostname)

    def _create_stream(self, addrinfo):
        af = addrinfo[0][0]
        if self.parsed.scheme == "https":
            ssl_options = {}
            if self.request.validate_cert:
                ssl_options["cert_reqs"] = ssl.CERT_REQUIRED
            if self.request.ca_certs is not None:
                ssl_options["ca_certs"] = self.request.ca_certs
            else:
                ssl_options["ca_certs"] = _DEFAULT_CA_CERTS
            if self.request.client_key is not None:
                ssl_options["keyfile"] = self.request.client_key
            if self.request.client_cert is not None:
                ssl_options["certfile"] = self.request.client_cert

            # SSL interoperability is tricky.  We want to disable
            # SSLv2 for security reasons; it wasn't disabled by default
            # until openssl 1.0.  The best way to do this is to use
            # the SSL_OP_NO_SSLv2, but that wasn't exposed to python
            # until 3.2.  Python 2.7 adds the ciphers argument, which
            # can also be used to disable SSLv2.  As a last resort
            # on python 2.6, we set ssl_version to SSLv3.  This is
            # more narrow than we'd like since it also breaks
            # compatibility with servers configured for TLSv1 only,
            # but nearly all servers support SSLv3:
            # http://blog.ivanristic.com/2011/09/ssl-survey-protocol-support.html
            if sys.version_info >= (2, 7):
                ssl_options["ciphers"] = "DEFAULT:!SSLv2"
            else:
                # This is really only necessary for pre-1.0 versions
                # of openssl, but python 2.6 doesn't expose version
                # information.
                ssl_options["ssl_version"] = ssl.PROTOCOL_SSLv3

            return SSLIOStream(socket.socket(af),
                               io_loop=self.io_loop,
                               ssl_options=ssl_options,
                               max_buffer_size=self.max_buffer_size)
        else:
            return IOStream(socket.socket(af),
                            io_loop=self.io_loop,
                            max_buffer_size=self.max_buffer_size)

    def _on_timeout(self):
        self._timeout = None
        if self.final_callback is not None:
            raise HTTPError(599, "Timeout")

    def _remove_timeout(self):
        if self._timeout is not None:
            self.io_loop.remove_timeout(self._timeout)
            self._timeout = None

    def _on_connect(self):
        self._remove_timeout()
        if self.request.request_timeout:
            self._timeout = self.io_loop.add_timeout(
                self.start_time + self.request.request_timeout,
                stack_context.wrap(self._on_timeout))
        if (self.request.method not in self._SUPPORTED_METHODS and
                not self.request.allow_nonstandard_methods):
            raise KeyError("unknown method %s" % self.request.method)
        for key in ('network_interface',
                    'proxy_host', 'proxy_port',
                    'proxy_username', 'proxy_password'):
            if getattr(self.request, key, None):
                raise NotImplementedError('%s not supported' % key)
        if "Connection" not in self.request.headers:
            self.request.headers["Connection"] = "close"
        if "Host" not in self.request.headers:
            if '@' in self.parsed.netloc:
                self.request.headers["Host"] = self.parsed.netloc.rpartition('@')[-1]
            else:
                self.request.headers["Host"] = self.parsed.netloc
        username, password = None, None
        if self.parsed.username is not None:
            username, password = self.parsed.username, self.parsed.password
        elif self.request.auth_username is not None:
            username = self.request.auth_username
            password = self.request.auth_password or ''
        if username is not None:
            if self.request.auth_mode not in (None, "basic"):
                raise ValueError("unsupported auth_mode %s",
                                 self.request.auth_mode)
            auth = utf8(username) + b":" + utf8(password)
            self.request.headers["Authorization"] = (b"Basic " +
                                                     base64.b64encode(auth))
        if self.request.user_agent:
            self.request.headers["User-Agent"] = self.request.user_agent
        if not self.request.allow_nonstandard_methods:
            if self.request.method in ("POST", "PATCH", "PUT"):
                assert self.request.body is not None
            else:
                assert self.request.body is None
        if self.request.body is not None:
            self.request.headers["Content-Length"] = str(len(
                self.request.body))
        if (self.request.method == "POST" and
                "Content-Type" not in self.request.headers):
            self.request.headers["Content-Type"] = "application/x-www-form-urlencoded"
        if self.request.use_gzip:
            self.request.headers["Accept-Encoding"] = "gzip"
        req_path = ((self.parsed.path or '/') +
                   (('?' + self.parsed.query) if self.parsed.query else ''))
        request_lines = [utf8("%s %s HTTP/1.1" % (self.request.method,
                                                  req_path))]
        for k, v in self.request.headers.get_all():
            line = utf8(k) + b": " + utf8(v)
            if b'\n' in line:
                raise ValueError('Newline in header: ' + repr(line))
            request_lines.append(line)
        request_str = b"\r\n".join(request_lines) + b"\r\n\r\n"
        if self.request.body is not None:
            request_str += self.request.body
        self.stream.set_nodelay(True)
        self.stream.write(request_str)
        self.stream.read_until_regex(b"\r?\n\r?\n", self._on_headers)

    def _release(self):
        if self.release_callback is not None:
            release_callback = self.release_callback
            self.release_callback = None
            release_callback()

    def _run_callback(self, response):
        self._release()
        if self.final_callback is not None:
            final_callback = self.final_callback
            self.final_callback = None
            self.io_loop.add_callback(final_callback, response)

    def _handle_exception(self, typ, value, tb):
        if self.final_callback:
            self._remove_timeout()
            self._run_callback(HTTPResponse(self.request, 599, error=value,
                                            request_time=self.io_loop.time() - self.start_time,
                                            ))

            if hasattr(self, "stream"):
                self.stream.close()
            return True
        else:
            # If our callback has already been called, we are probably
            # catching an exception that is not caused by us but rather
            # some child of our callback. Rather than drop it on the floor,
            # pass it along.
            return False

    def _on_close(self):
        if self.final_callback is not None:
            message = "Connection closed"
            if self.stream.error:
                message = str(self.stream.error)
            raise HTTPError(599, message)

    def _handle_1xx(self, code):
        self.stream.read_until_regex(b"\r?\n\r?\n", self._on_headers)

    def _on_headers(self, data):
        data = native_str(data.decode("latin1"))
        first_line, _, header_data = data.partition("\n")
        match = re.match("HTTP/1.[01] ([0-9]+) ([^\r]*)", first_line)
        assert match
        code = int(match.group(1))
        self.headers = HTTPHeaders.parse(header_data)
        if 100 <= code < 200:
            self._handle_1xx(code)
            return
        else:
            self.code = code
            self.reason = match.group(2)

        if "Content-Length" in self.headers:
            if "," in self.headers["Content-Length"]:
                # Proxies sometimes cause Content-Length headers to get
                # duplicated.  If all the values are identical then we can
                # use them but if they differ it's an error.
                pieces = re.split(r',\s*', self.headers["Content-Length"])
                if any(i != pieces[0] for i in pieces):
                    raise ValueError("Multiple unequal Content-Lengths: %r" %
                                     self.headers["Content-Length"])
                self.headers["Content-Length"] = pieces[0]
            content_length = int(self.headers["Content-Length"])
        else:
            content_length = None

        if self.request.header_callback is not None:
            # re-attach the newline we split on earlier
            self.request.header_callback(first_line + _)
            for k, v in self.headers.get_all():
                self.request.header_callback("%s: %s\r\n" % (k, v))
            self.request.header_callback('\r\n')

        if self.request.method == "HEAD" or self.code == 304:
            # HEAD requests and 304 responses never have content, even
            # though they may have content-length headers
            self._on_body(b"")
            return
        if 100 <= self.code < 200 or self.code == 204:
            # These response codes never have bodies
            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3
            if ("Transfer-Encoding" in self.headers or
                    content_length not in (None, 0)):
                raise ValueError("Response with code %d should not have body" %
                                 self.code)
            self._on_body(b"")
            return

        if (self.request.use_gzip and
                self.headers.get("Content-Encoding") == "gzip"):
            self._decompressor = GzipDecompressor()
        if self.headers.get("Transfer-Encoding") == "chunked":
            self.chunks = []
            self.stream.read_until(b"\r\n", self._on_chunk_length)
        elif content_length is not None:
            self.stream.read_bytes(content_length, self._on_body)
        else:
            self.stream.read_until_close(self._on_body)

    def _on_body(self, data):
        self._remove_timeout()
        original_request = getattr(self.request, "original_request",
                                   self.request)
        if (self.request.follow_redirects and
            self.request.max_redirects > 0 and
                self.code in (301, 302, 303, 307)):
            assert isinstance(self.request, _RequestProxy)
            new_request = copy.copy(self.request.request)
            new_request.url = urlparse.urljoin(self.request.url,
                                               self.headers["Location"])
            new_request.max_redirects = self.request.max_redirects - 1
            del new_request.headers["Host"]
            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4
            # Client SHOULD make a GET request after a 303.
            # According to the spec, 302 should be followed by the same
            # method as the original request, but in practice browsers
            # treat 302 the same as 303, and many servers use 302 for
            # compatibility with pre-HTTP/1.1 user agents which don't
            # understand the 303 status.
            if self.code in (302, 303):
                new_request.method = "GET"
                new_request.body = None
                for h in ["Content-Length", "Content-Type",
                          "Content-Encoding", "Transfer-Encoding"]:
                    try:
                        del self.request.headers[h]
                    except KeyError:
                        pass
            new_request.original_request = original_request
            final_callback = self.final_callback
            self.final_callback = None
            self._release()
            self.client.fetch(new_request, final_callback)
            self._on_end_request()
            return
        if self._decompressor:
            data = (self._decompressor.decompress(data) +
                    self._decompressor.flush())
        if self.request.streaming_callback:
            if self.chunks is None:
                # if chunks is not None, we already called streaming_callback
                # in _on_chunk_data
                self.request.streaming_callback(data)
            buffer = BytesIO()
        else:
            buffer = BytesIO(data)  # TODO: don't require one big string?
        response = HTTPResponse(original_request,
                                self.code, reason=self.reason,
                                headers=self.headers,
                                request_time=self.io_loop.time() - self.start_time,
                                buffer=buffer,
                                effective_url=self.request.url)
        self._run_callback(response)
        self._on_end_request()

    def _on_end_request(self):
        self.stream.close()

    def _on_chunk_length(self, data):
        # TODO: "chunk extensions" http://tools.ietf.org/html/rfc2616#section-3.6.1
        length = int(data.strip(), 16)
        if length == 0:
            if self._decompressor is not None:
                tail = self._decompressor.flush()
                if tail:
                    # I believe the tail will always be empty (i.e.
                    # decompress will return all it can).  The purpose
                    # of the flush call is to detect errors such
                    # as truncated input.  But in case it ever returns
                    # anything, treat it as an extra chunk
                    if self.request.streaming_callback is not None:
                        self.request.streaming_callback(tail)
                    else:
                        self.chunks.append(tail)
                # all the data has been decompressed, so we don't need to
                # decompress again in _on_body
                self._decompressor = None
            self._on_body(b''.join(self.chunks))
        else:
            self.stream.read_bytes(length + 2,  # chunk ends with \r\n
                                   self._on_chunk_data)

    def _on_chunk_data(self, data):
        assert data[-2:] == b"\r\n"
        chunk = data[:-2]
        if self._decompressor:
            chunk = self._decompressor.decompress(chunk)
        if self.request.streaming_callback is not None:
            self.request.streaming_callback(chunk)
        else:
            self.chunks.append(chunk)
        self.stream.read_until(b"\r\n", self._on_chunk_length)


if __name__ == "__main__":
    AsyncHTTPClient.configure(SimpleAsyncHTTPClient)
    main()

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
user