{
    "file_diffs": [
        {
            "old_file_content": "#!/usr/bin/env python\n#\n# Copyright 2014 Facebook\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n\n\"\"\"Client and server implementations of HTTP/1.x.\n\n.. versionadded:: 4.0\n\"\"\"\n\nfrom __future__ import absolute_import, division, print_function, with_statement\n\nimport re\n\nfrom tornado.concurrent import Future\nfrom tornado.escape import native_str, utf8\nfrom tornado import gen\nfrom tornado import httputil\nfrom tornado import iostream\nfrom tornado.log import gen_log, app_log\nfrom tornado import stack_context\nfrom tornado.util import GzipDecompressor, PY3\n\n\nclass _QuietException(Exception):\n    def __init__(self):\n        pass\n\n\nclass _ExceptionLoggingContext(object):\n    \"\"\"Used with the ``with`` statement when calling delegate methods to\n    log any exceptions with the given logger.  Any exceptions caught are\n    converted to _QuietException\n    \"\"\"\n    def __init__(self, logger):\n        self.logger = logger\n\n    def __enter__(self):\n        pass\n\n    def __exit__(self, typ, value, tb):\n        if value is not None:\n            self.logger.error(\"Uncaught exception\", exc_info=(typ, value, tb))\n            raise _QuietException\n\n\nclass HTTP1ConnectionParameters(object):\n    \"\"\"Parameters for `.HTTP1Connection` and `.HTTP1ServerConnection`.\n    \"\"\"\n    def __init__(self, no_keep_alive=False, chunk_size=None,\n                 max_header_size=None, header_timeout=None, max_body_size=None,\n                 body_timeout=None, decompress=False):\n        \"\"\"\n        :arg bool no_keep_alive: If true, always close the connection after\n            one request.\n        :arg int chunk_size: how much data to read into memory at once\n        :arg int max_header_size:  maximum amount of data for HTTP headers\n        :arg float header_timeout: how long to wait for all headers (seconds)\n        :arg int max_body_size: maximum amount of data for body\n        :arg float body_timeout: how long to wait while reading body (seconds)\n        :arg bool decompress: if true, decode incoming\n            ``Content-Encoding: gzip``\n        \"\"\"\n        self.no_keep_alive = no_keep_alive\n        self.chunk_size = chunk_size or 65536\n        self.max_header_size = max_header_size or 65536\n        self.header_timeout = header_timeout\n        self.max_body_size = max_body_size\n        self.body_timeout = body_timeout\n        self.decompress = decompress\n\n\nclass HTTP1Connection(httputil.HTTPConnection):\n    \"\"\"Implements the HTTP/1.x protocol.\n\n    This class can be on its own for clients, or via `HTTP1ServerConnection`\n    for servers.\n    \"\"\"\n    def __init__(self, stream, is_client, params=None, context=None):\n        \"\"\"\n        :arg stream: an `.IOStream`\n        :arg bool is_client: client or server\n        :arg params: a `.HTTP1ConnectionParameters` instance or ``None``\n        :arg context: an opaque application-defined object that can be accessed\n            as ``connection.context``.\n        \"\"\"\n        self.is_client = is_client\n        self.stream = stream\n        if params is None:\n            params = HTTP1ConnectionParameters()\n        self.params = params\n        self.context = context\n        self.no_keep_alive = params.no_keep_alive\n        # The body limits can be altered by the delegate, so save them\n        # here instead of just referencing self.params later.\n        self._max_body_size = (self.params.max_body_size or\n                               self.stream.max_buffer_size)\n        self._body_timeout = self.params.body_timeout\n        # _write_finished is set to True when finish() has been called,\n        # i.e. there will be no more data sent.  Data may still be in the\n        # stream's write buffer.\n        self._write_finished = False\n        # True when we have read the entire incoming body.\n        self._read_finished = False\n        # _finish_future resolves when all data has been written and flushed\n        # to the IOStream.\n        self._finish_future = Future()\n        # If true, the connection should be closed after this request\n        # (after the response has been written in the server side,\n        # and after it has been read in the client)\n        self._disconnect_on_finish = False\n        self._clear_callbacks()\n        # Save the start lines after we read or write them; they\n        # affect later processing (e.g. 304 responses and HEAD methods\n        # have content-length but no bodies)\n        self._request_start_line = None\n        self._response_start_line = None\n        self._request_headers = None\n        # True if we are writing output with chunked encoding.\n        self._chunking_output = None\n        # While reading a body with a content-length, this is the\n        # amount left to read.\n        self._expected_content_remaining = None\n        # A Future for our outgoing writes, returned by IOStream.write.\n        self._pending_write = None\n\n    def read_response(self, delegate):\n        \"\"\"Read a single HTTP response.\n\n        Typical client-mode usage is to write a request using `write_headers`,\n        `write`, and `finish`, and then call ``read_response``.\n\n        :arg delegate: a `.HTTPMessageDelegate`\n\n        Returns a `.Future` that resolves to None after the full response has\n        been read.\n        \"\"\"\n        if self.params.decompress:\n            delegate = _GzipMessageDelegate(delegate, self.params.chunk_size)\n        return self._read_message(delegate)\n\n    @gen.coroutine\n    def _read_message(self, delegate):\n        need_delegate_close = False\n        try:\n            header_future = self.stream.read_until_regex(\n                b\"\\r?\\n\\r?\\n\",\n                max_bytes=self.params.max_header_size)\n            if self.params.header_timeout is None:\n                header_data = yield header_future\n            else:\n                try:\n                    header_data = yield gen.with_timeout(\n                        self.stream.io_loop.time() + self.params.header_timeout,\n                        header_future,\n                        io_loop=self.stream.io_loop,\n                        quiet_exceptions=iostream.StreamClosedError)\n                except gen.TimeoutError:\n                    self.close()\n                    raise gen.Return(False)\n            start_line, headers = self._parse_headers(header_data)\n            if self.is_client:\n                start_line = httputil.parse_response_start_line(start_line)\n                self._response_start_line = start_line\n            else:\n                start_line = httputil.parse_request_start_line(start_line)\n                self._request_start_line = start_line\n                self._request_headers = headers\n\n            self._disconnect_on_finish = not self._can_keep_alive(\n                start_line, headers)\n            need_delegate_close = True\n            with _ExceptionLoggingContext(app_log):\n                header_future = delegate.headers_received(start_line, headers)\n                if header_future is not None:\n                    yield header_future\n            if self.stream is None:\n                # We've been detached.\n                need_delegate_close = False\n                raise gen.Return(False)\n            skip_body = False\n            if self.is_client:\n                if (self._request_start_line is not None and\n                        self._request_start_line.method == 'HEAD'):\n                    skip_body = True\n                code = start_line.code\n                if code == 304:\n                    # 304 responses may include the content-length header\n                    # but do not actually have a body.\n                    # http://tools.ietf.org/html/rfc7230#section-3.3\n                    skip_body = True\n                if code >= 100 and code < 200:\n                    # 1xx responses should never indicate the presence of\n                    # a body.\n                    if ('Content-Length' in headers or\n                            'Transfer-Encoding' in headers):\n                        raise httputil.HTTPInputError(\n                            \"Response code %d cannot have body\" % code)\n                    # TODO: client delegates will get headers_received twice\n                    # in the case of a 100-continue.  Document or change?\n                    yield self._read_message(delegate)\n            else:\n                if (headers.get(\"Expect\") == \"100-continue\" and\n                        not self._write_finished):\n                    self.stream.write(b\"HTTP/1.1 100 (Continue)\\r\\n\\r\\n\")\n            if not skip_body:\n                body_future = self._read_body(\n                    start_line.code if self.is_client else 0, headers, delegate)\n                if body_future is not None:\n                    if self._body_timeout is None:\n                        yield body_future\n                    else:\n                        try:\n                            yield gen.with_timeout(\n                                self.stream.io_loop.time() + self._body_timeout,\n                                body_future, self.stream.io_loop,\n                                quiet_exceptions=iostream.StreamClosedError)\n                        except gen.TimeoutError:\n                            gen_log.info(\"Timeout reading body from %s\",\n                                         self.context)\n                            self.stream.close()\n                            raise gen.Return(False)\n            self._read_finished = True\n            if not self._write_finished or self.is_client:\n                need_delegate_close = False\n                with _ExceptionLoggingContext(app_log):\n                    delegate.finish()\n            # If we're waiting for the application to produce an asynchronous\n            # response, and we're not detached, register a close callback\n            # on the stream (we didn't need one while we were reading)\n            if (not self._finish_future.done() and\n                    self.stream is not None and\n                    not self.stream.closed()):\n                self.stream.set_close_callback(self._on_connection_close)\n                yield self._finish_future\n            if self.is_client and self._disconnect_on_finish:\n                self.close()\n            if self.stream is None:\n                raise gen.Return(False)\n        except httputil.HTTPInputError as e:\n            gen_log.info(\"Malformed HTTP message from %s: %s\",\n                         self.context, e)\n            self.close()\n            raise gen.Return(False)\n        finally:\n            if need_delegate_close:\n                with _ExceptionLoggingContext(app_log):\n                    delegate.on_connection_close()\n            self._clear_callbacks()\n        raise gen.Return(True)\n\n    def _clear_callbacks(self):\n        \"\"\"Clears the callback attributes.\n\n        This allows the request handler to be garbage collected more\n        quickly in CPython by breaking up reference cycles.\n        \"\"\"\n        self._write_callback = None\n        self._write_future = None\n        self._close_callback = None\n        if self.stream is not None:\n            self.stream.set_close_callback(None)\n\n    def set_close_callback(self, callback):\n        \"\"\"Sets a callback that will be run when the connection is closed.\n\n        .. deprecated:: 4.0\n            Use `.HTTPMessageDelegate.on_connection_close` instead.\n        \"\"\"\n        self._close_callback = stack_context.wrap(callback)\n\n    def _on_connection_close(self):\n        # Note that this callback is only registered on the IOStream\n        # when we have finished reading the request and are waiting for\n        # the application to produce its response.\n        if self._close_callback is not None:\n            callback = self._close_callback\n            self._close_callback = None\n            callback()\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n        self._clear_callbacks()\n\n    def close(self):\n        if self.stream is not None:\n            self.stream.close()\n        self._clear_callbacks()\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n\n    def detach(self):\n        \"\"\"Take control of the underlying stream.\n\n        Returns the underlying `.IOStream` object and stops all further\n        HTTP processing.  May only be called during\n        `.HTTPMessageDelegate.headers_received`.  Intended for implementing\n        protocols like websockets that tunnel over an HTTP handshake.\n        \"\"\"\n        self._clear_callbacks()\n        stream = self.stream\n        self.stream = None\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n        return stream\n\n    def set_body_timeout(self, timeout):\n        \"\"\"Sets the body timeout for a single request.\n\n        Overrides the value from `.HTTP1ConnectionParameters`.\n        \"\"\"\n        self._body_timeout = timeout\n\n    def set_max_body_size(self, max_body_size):\n        \"\"\"Sets the body size limit for a single request.\n\n        Overrides the value from `.HTTP1ConnectionParameters`.\n        \"\"\"\n        self._max_body_size = max_body_size\n\n    def write_headers(self, start_line, headers, chunk=None, callback=None):\n        \"\"\"Implements `.HTTPConnection.write_headers`.\"\"\"\n        lines = []\n        if self.is_client:\n            self._request_start_line = start_line\n            lines.append(utf8('%s %s HTTP/1.1' % (start_line[0], start_line[1])))\n            # Client requests with a non-empty body must have either a\n            # Content-Length or a Transfer-Encoding.\n            self._chunking_output = (\n                start_line.method in ('POST', 'PUT', 'PATCH') and\n                'Content-Length' not in headers and\n                'Transfer-Encoding' not in headers)\n        else:\n            self._response_start_line = start_line\n            lines.append(utf8('HTTP/1.1 %d %s' % (start_line[1], start_line[2])))\n            self._chunking_output = (\n                # TODO: should this use\n                # self._request_start_line.version or\n                # start_line.version?\n                self._request_start_line.version == 'HTTP/1.1' and\n                # 304 responses have no body (not even a zero-length body), and so\n                # should not have either Content-Length or Transfer-Encoding.\n                # headers.\n                start_line.code not in (204, 304) and\n                # No need to chunk the output if a Content-Length is specified.\n                'Content-Length' not in headers and\n                # Applications are discouraged from touching Transfer-Encoding,\n                # but if they do, leave it alone.\n                'Transfer-Encoding' not in headers)\n            # If a 1.0 client asked for keep-alive, add the header.\n            if (self._request_start_line.version == 'HTTP/1.0' and\n                (self._request_headers.get('Connection', '').lower() ==\n                 'keep-alive')):\n                headers['Connection'] = 'Keep-Alive'\n        if self._chunking_output:\n            headers['Transfer-Encoding'] = 'chunked'\n        if (not self.is_client and\n            (self._request_start_line.method == 'HEAD' or\n             start_line.code == 304)):\n            self._expected_content_remaining = 0\n        elif 'Content-Length' in headers:\n            self._expected_content_remaining = int(headers['Content-Length'])\n        else:\n            self._expected_content_remaining = None\n        # TODO: headers are supposed to be of type str, but we still have some\n        # cases that let bytes slip through. Remove these native_str calls when those\n        # are fixed.\n        header_lines = (native_str(n) + \": \" + native_str(v) for n, v in headers.get_all())\n        if PY3:\n            lines.extend(l.encode('latin1') for l in header_lines)\n        else:\n            lines.extend(header_lines)\n        for line in lines:\n            if b'\\n' in line:\n                raise ValueError('Newline in header: ' + repr(line))\n        future = None\n        if self.stream.closed():\n            future = self._write_future = Future()\n            future.set_exception(iostream.StreamClosedError())\n            future.exception()\n        else:\n            if callback is not None:\n                self._write_callback = stack_context.wrap(callback)\n            else:\n                future = self._write_future = Future()\n            data = b\"\\r\\n\".join(lines) + b\"\\r\\n\\r\\n\"\n            if chunk:\n                data += self._format_chunk(chunk)\n            self._pending_write = self.stream.write(data)\n            self._pending_write.add_done_callback(self._on_write_complete)\n        return future\n\n    def _format_chunk(self, chunk):\n        if self._expected_content_remaining is not None:\n            self._expected_content_remaining -= len(chunk)\n            if self._expected_content_remaining < 0:\n                # Close the stream now to stop further framing errors.\n                self.stream.close()\n                raise httputil.HTTPOutputError(\n                    \"Tried to write more data than Content-Length\")\n        if self._chunking_output and chunk:\n            # Don't write out empty chunks because that means END-OF-STREAM\n            # with chunked encoding\n            return utf8(\"%x\" % len(chunk)) + b\"\\r\\n\" + chunk + b\"\\r\\n\"\n        else:\n            return chunk\n\n    def write(self, chunk, callback=None):\n        \"\"\"Implements `.HTTPConnection.write`.\n\n        For backwards compatibility is is allowed but deprecated to\n        skip `write_headers` and instead call `write()` with a\n        pre-encoded header block.\n        \"\"\"\n        future = None\n        if self.stream.closed():\n            future = self._write_future = Future()\n            self._write_future.set_exception(iostream.StreamClosedError())\n            self._write_future.exception()\n        else:\n            if callback is not None:\n                self._write_callback = stack_context.wrap(callback)\n            else:\n                future = self._write_future = Future()\n            self._pending_write = self.stream.write(self._format_chunk(chunk))\n            self._pending_write.add_done_callback(self._on_write_complete)\n        return future\n\n    def finish(self):\n        \"\"\"Implements `.HTTPConnection.finish`.\"\"\"\n        if (self._expected_content_remaining is not None and\n                self._expected_content_remaining != 0 and\n                not self.stream.closed()):\n            self.stream.close()\n            raise httputil.HTTPOutputError(\n                \"Tried to write %d bytes less than Content-Length\" %\n                self._expected_content_remaining)\n        if self._chunking_output:\n            if not self.stream.closed():\n                self._pending_write = self.stream.write(b\"0\\r\\n\\r\\n\")\n                self._pending_write.add_done_callback(self._on_write_complete)\n        self._write_finished = True\n        # If the app finished the request while we're still reading,\n        # divert any remaining data away from the delegate and\n        # close the connection when we're done sending our response.\n        # Closing the connection is the only way to avoid reading the\n        # whole input body.\n        if not self._read_finished:\n            self._disconnect_on_finish = True\n        # No more data is coming, so instruct TCP to send any remaining\n        # data immediately instead of waiting for a full packet or ack.\n        self.stream.set_nodelay(True)\n        if self._pending_write is None:\n            self._finish_request(None)\n        else:\n            self._pending_write.add_done_callback(self._finish_request)\n\n    def _on_write_complete(self, future):\n        exc = future.exception()\n        if exc is not None and not isinstance(exc, iostream.StreamClosedError):\n            future.result()\n        if self._write_callback is not None:\n            callback = self._write_callback\n            self._write_callback = None\n            self.stream.io_loop.add_callback(callback)\n        if self._write_future is not None:\n            future = self._write_future\n            self._write_future = None\n            future.set_result(None)\n\n    def _can_keep_alive(self, start_line, headers):\n        if self.params.no_keep_alive:\n            return False\n        connection_header = headers.get(\"Connection\")\n        if connection_header is not None:\n            connection_header = connection_header.lower()\n        if start_line.version == \"HTTP/1.1\":\n            return connection_header != \"close\"\n        elif (\"Content-Length\" in headers or\n              headers.get(\"Transfer-Encoding\", \"\").lower() == \"chunked\" or\n              getattr(start_line, 'method', None) in (\"HEAD\", \"GET\")):\n            # start_line may be a request or reponse start line; only\n            # the former has a method attribute.\n            return connection_header == \"keep-alive\"\n        return False\n\n    def _finish_request(self, future):\n        self._clear_callbacks()\n        if not self.is_client and self._disconnect_on_finish:\n            self.close()\n            return\n        # Turn Nagle's algorithm back on, leaving the stream in its\n        # default state for the next request.\n        self.stream.set_nodelay(False)\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n\n    def _parse_headers(self, data):\n        # The lstrip removes newlines that some implementations sometimes\n        # insert between messages of a reused connection.  Per RFC 7230,\n        # we SHOULD ignore at least one empty line before the request.\n        # http://tools.ietf.org/html/rfc7230#section-3.5\n        data = native_str(data.decode('latin1')).lstrip(\"\\r\\n\")\n        # RFC 7230 section allows for both CRLF and bare LF.\n        eol = data.find(\"\\n\")\n        start_line = data[:eol].rstrip(\"\\r\")\n        try:\n            headers = httputil.HTTPHeaders.parse(data[eol:])\n        except ValueError:\n            # probably form split() if there was no ':' in the line\n            raise httputil.HTTPInputError(\"Malformed HTTP headers: %r\" %\n                                          data[eol:100])\n        return start_line, headers\n\n    def _read_body(self, code, headers, delegate):\n        if \"Content-Length\" in headers:\n            if \"Transfer-Encoding\" in headers:\n                # Response cannot contain both Content-Length and\n                # Transfer-Encoding headers.\n                # http://tools.ietf.org/html/rfc7230#section-3.3.3\n                raise httputil.HTTPInputError(\n                    \"Response with both Transfer-Encoding and Content-Length\")\n            if \",\" in 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*', headers[\"Content-Length\"])\n                if any(i != pieces[0] for i in pieces):\n                    raise httputil.HTTPInputError(\n                        \"Multiple unequal Content-Lengths: %r\" %\n                        headers[\"Content-Length\"])\n                headers[\"Content-Length\"] = pieces[0]\n\n            try:\n                content_length = int(headers[\"Content-Length\"])\n            except ValueError:\n                # Handles non-integer Content-Length value.\n                raise httputil.HTTPInputError(\n                    \"Only integer Content-Length is allowed: %s\" % headers[\"Content-Length\"])\n\n            if content_length > self._max_body_size:\n                raise httputil.HTTPInputError(\"Content-Length too long\")\n        else:\n            content_length = None\n\n        if code == 204:\n            # This response code is not allowed to have a non-empty body,\n            # and has an implicit length of zero instead of read-until-close.\n            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3\n            if (\"Transfer-Encoding\" in headers or\n                    content_length not in (None, 0)):\n                raise httputil.HTTPInputError(\n                    \"Response with code %d should not have body\" % code)\n            content_length = 0\n\n        if content_length is not None:\n            return self._read_fixed_body(content_length, delegate)\n        if headers.get(\"Transfer-Encoding\") == \"chunked\":\n            return self._read_chunked_body(delegate)\n        if self.is_client:\n            return self._read_body_until_close(delegate)\n        return None\n\n    @gen.coroutine\n    def _read_fixed_body(self, content_length, delegate):\n        while content_length > 0:\n            body = yield self.stream.read_bytes(\n                min(self.params.chunk_size, content_length), partial=True)\n            content_length -= len(body)\n            if not self._write_finished or self.is_client:\n                with _ExceptionLoggingContext(app_log):\n                    ret = delegate.data_received(body)\n                    if ret is not None:\n                        yield ret\n\n    @gen.coroutine\n    def _read_chunked_body(self, delegate):\n        # TODO: \"chunk extensions\" http://tools.ietf.org/html/rfc2616#section-3.6.1\n        total_size = 0\n        while True:\n            chunk_len = yield self.stream.read_until(b\"\\r\\n\", max_bytes=64)\n            chunk_len = int(chunk_len.strip(), 16)\n            if chunk_len == 0:\n                return\n            total_size += chunk_len\n            if total_size > self._max_body_size:\n                raise httputil.HTTPInputError(\"chunked body too large\")\n            bytes_to_read = chunk_len\n            while bytes_to_read:\n                chunk = yield self.stream.read_bytes(\n                    min(bytes_to_read, self.params.chunk_size), partial=True)\n                bytes_to_read -= len(chunk)\n                if not self._write_finished or self.is_client:\n                    with _ExceptionLoggingContext(app_log):\n                        ret = delegate.data_received(chunk)\n                        if ret is not None:\n                            yield ret\n            # chunk ends with \\r\\n\n            crlf = yield self.stream.read_bytes(2)\n            assert crlf == b\"\\r\\n\"\n\n    @gen.coroutine\n    def _read_body_until_close(self, delegate):\n        body = yield self.stream.read_until_close()\n        if not self._write_finished or self.is_client:\n            with _ExceptionLoggingContext(app_log):\n                delegate.data_received(body)\n\n\nclass _GzipMessageDelegate(httputil.HTTPMessageDelegate):\n    \"\"\"Wraps an `HTTPMessageDelegate` to decode ``Content-Encoding: gzip``.\n    \"\"\"\n    def __init__(self, delegate, chunk_size):\n        self._delegate = delegate\n        self._chunk_size = chunk_size\n        self._decompressor = None\n\n    def headers_received(self, start_line, headers):\n        if headers.get(\"Content-Encoding\") == \"gzip\":\n            self._decompressor = GzipDecompressor()\n            # Downstream delegates will only see uncompressed data,\n            # so rename the content-encoding header.\n            # (but note that curl_httpclient doesn't do this).\n            headers.add(\"X-Consumed-Content-Encoding\",\n                        headers[\"Content-Encoding\"])\n            del headers[\"Content-Encoding\"]\n        return self._delegate.headers_received(start_line, headers)\n\n    @gen.coroutine\n    def data_received(self, chunk):\n        if self._decompressor:\n            compressed_data = chunk\n            while compressed_data:\n                decompressed = self._decompressor.decompress(\n                    compressed_data, self._chunk_size)\n                if decompressed:\n                    ret = self._delegate.data_received(decompressed)\n                    if ret is not None:\n                        yield ret\n                compressed_data = self._decompressor.unconsumed_tail\n        else:\n            ret = self._delegate.data_received(chunk)\n            if ret is not None:\n                yield ret\n\n    def finish(self):\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                self._delegate.data_received(tail)\n        return self._delegate.finish()\n\n    def on_connection_close(self):\n        return self._delegate.on_connection_close()\n\n\nclass HTTP1ServerConnection(object):\n    \"\"\"An HTTP/1.x server.\"\"\"\n    def __init__(self, stream, params=None, context=None):\n        \"\"\"\n        :arg stream: an `.IOStream`\n        :arg params: a `.HTTP1ConnectionParameters` or None\n        :arg context: an opaque application-defined object that is accessible\n            as ``connection.context``\n        \"\"\"\n        self.stream = stream\n        if params is None:\n            params = HTTP1ConnectionParameters()\n        self.params = params\n        self.context = context\n        self._serving_future = None\n\n    @gen.coroutine\n    def close(self):\n        \"\"\"Closes the connection.\n\n        Returns a `.Future` that resolves after the serving loop has exited.\n        \"\"\"\n        self.stream.close()\n        # Block until the serving loop is done, but ignore any exceptions\n        # (start_serving is already responsible for logging them).\n        try:\n            yield self._serving_future\n        except Exception:\n            pass\n\n    def start_serving(self, delegate):\n        \"\"\"Starts serving requests on this connection.\n\n        :arg delegate: a `.HTTPServerConnectionDelegate`\n        \"\"\"\n        assert isinstance(delegate, httputil.HTTPServerConnectionDelegate)\n        self._serving_future = self._server_request_loop(delegate)\n        # Register the future on the IOLoop so its errors get logged.\n        self.stream.io_loop.add_future(self._serving_future,\n                                       lambda f: f.result())\n\n    @gen.coroutine\n    def _server_request_loop(self, delegate):\n        try:\n            while True:\n                conn = HTTP1Connection(self.stream, False,\n                                       self.params, self.context)\n                request_delegate = delegate.start_request(self, conn)\n                try:\n                    ret = yield conn.read_response(request_delegate)\n                except (iostream.StreamClosedError,\n                        iostream.UnsatisfiableReadError):\n                    return\n                except _QuietException:\n                    # This exception was already logged.\n                    conn.close()\n                    return\n                except Exception:\n                    gen_log.error(\"Uncaught exception\", exc_info=True)\n                    conn.close()\n                    return\n                if not ret:\n                    return\n                yield gen.moment\n        finally:\n            delegate.on_close(self)\n",
            "new_file_content": "#!/usr/bin/env python\n#\n# Copyright 2014 Facebook\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n\n\"\"\"Client and server implementations of HTTP/1.x.\n\n.. versionadded:: 4.0\n\"\"\"\n\nfrom __future__ import absolute_import, division, print_function, with_statement\n\nimport re\n\nfrom tornado.concurrent import Future\nfrom tornado.escape import native_str, utf8\nfrom tornado import gen\nfrom tornado import httputil\nfrom tornado import iostream\nfrom tornado.log import gen_log, app_log\nfrom tornado import stack_context\nfrom tornado.util import GzipDecompressor, PY3\n\n\nclass _QuietException(Exception):\n    def __init__(self):\n        pass\n\n\nclass _ExceptionLoggingContext(object):\n    \"\"\"Used with the ``with`` statement when calling delegate methods to\n    log any exceptions with the given logger.  Any exceptions caught are\n    converted to _QuietException\n    \"\"\"\n    def __init__(self, logger):\n        self.logger = logger\n\n    def __enter__(self):\n        pass\n\n    def __exit__(self, typ, value, tb):\n        if value is not None:\n            self.logger.error(\"Uncaught exception\", exc_info=(typ, value, tb))\n            raise _QuietException\n\n\nclass HTTP1ConnectionParameters(object):\n    \"\"\"Parameters for `.HTTP1Connection` and `.HTTP1ServerConnection`.\n    \"\"\"\n    def __init__(self, no_keep_alive=False, chunk_size=None,\n                 max_header_size=None, header_timeout=None, max_body_size=None,\n                 body_timeout=None, decompress=False):\n        \"\"\"\n        :arg bool no_keep_alive: If true, always close the connection after\n            one request.\n        :arg int chunk_size: how much data to read into memory at once\n        :arg int max_header_size:  maximum amount of data for HTTP headers\n        :arg float header_timeout: how long to wait for all headers (seconds)\n        :arg int max_body_size: maximum amount of data for body\n        :arg float body_timeout: how long to wait while reading body (seconds)\n        :arg bool decompress: if true, decode incoming\n            ``Content-Encoding: gzip``\n        \"\"\"\n        self.no_keep_alive = no_keep_alive\n        self.chunk_size = chunk_size or 65536\n        self.max_header_size = max_header_size or 65536\n        self.header_timeout = header_timeout\n        self.max_body_size = max_body_size\n        self.body_timeout = body_timeout\n        self.decompress = decompress\n\n\nclass HTTP1Connection(httputil.HTTPConnection):\n    \"\"\"Implements the HTTP/1.x protocol.\n\n    This class can be on its own for clients, or via `HTTP1ServerConnection`\n    for servers.\n    \"\"\"\n    def __init__(self, stream, is_client, params=None, context=None):\n        \"\"\"\n        :arg stream: an `.IOStream`\n        :arg bool is_client: client or server\n        :arg params: a `.HTTP1ConnectionParameters` instance or ``None``\n        :arg context: an opaque application-defined object that can be accessed\n            as ``connection.context``.\n        \"\"\"\n        self.is_client = is_client\n        self.stream = stream\n        if params is None:\n            params = HTTP1ConnectionParameters()\n        self.params = params\n        self.context = context\n        self.no_keep_alive = params.no_keep_alive\n        # The body limits can be altered by the delegate, so save them\n        # here instead of just referencing self.params later.\n        self._max_body_size = (self.params.max_body_size or\n                               self.stream.max_buffer_size)\n        self._body_timeout = self.params.body_timeout\n        # _write_finished is set to True when finish() has been called,\n        # i.e. there will be no more data sent.  Data may still be in the\n        # stream's write buffer.\n        self._write_finished = False\n        # True when we have read the entire incoming body.\n        self._read_finished = False\n        # _finish_future resolves when all data has been written and flushed\n        # to the IOStream.\n        self._finish_future = Future()\n        # If true, the connection should be closed after this request\n        # (after the response has been written in the server side,\n        # and after it has been read in the client)\n        self._disconnect_on_finish = False\n        self._clear_callbacks()\n        # Save the start lines after we read or write them; they\n        # affect later processing (e.g. 304 responses and HEAD methods\n        # have content-length but no bodies)\n        self._request_start_line = None\n        self._response_start_line = None\n        self._request_headers = None\n        # True if we are writing output with chunked encoding.\n        self._chunking_output = None\n        # While reading a body with a content-length, this is the\n        # amount left to read.\n        self._expected_content_remaining = None\n        # A Future for our outgoing writes, returned by IOStream.write.\n        self._pending_write = None\n\n    def read_response(self, delegate):\n        \"\"\"Read a single HTTP response.\n\n        Typical client-mode usage is to write a request using `write_headers`,\n        `write`, and `finish`, and then call ``read_response``.\n\n        :arg delegate: a `.HTTPMessageDelegate`\n\n        Returns a `.Future` that resolves to None after the full response has\n        been read.\n        \"\"\"\n        if self.params.decompress:\n            delegate = _GzipMessageDelegate(delegate, self.params.chunk_size)\n        return self._read_message(delegate)\n\n    @gen.coroutine\n    def _read_message(self, delegate):\n        need_delegate_close = False\n        try:\n            header_future = self.stream.read_until_regex(\n                b\"\\r?\\n\\r?\\n\",\n                max_bytes=self.params.max_header_size)\n            if self.params.header_timeout is None:\n                header_data = yield header_future\n            else:\n                try:\n                    header_data = yield gen.with_timeout(\n                        self.stream.io_loop.time() + self.params.header_timeout,\n                        header_future,\n                        io_loop=self.stream.io_loop,\n                        quiet_exceptions=iostream.StreamClosedError)\n                except gen.TimeoutError:\n                    self.close()\n                    raise gen.Return(False)\n            start_line, headers = self._parse_headers(header_data)\n            if self.is_client:\n                start_line = httputil.parse_response_start_line(start_line)\n                self._response_start_line = start_line\n            else:\n                start_line = httputil.parse_request_start_line(start_line)\n                self._request_start_line = start_line\n                self._request_headers = headers\n\n            self._disconnect_on_finish = not self._can_keep_alive(\n                start_line, headers)\n            need_delegate_close = True\n            with _ExceptionLoggingContext(app_log):\n                header_future = delegate.headers_received(start_line, headers)\n                if header_future is not None:\n                    yield header_future\n            if self.stream is None:\n                # We've been detached.\n                need_delegate_close = False\n                raise gen.Return(False)\n            skip_body = False\n            if self.is_client:\n                if (self._request_start_line is not None and\n                        self._request_start_line.method == 'HEAD'):\n                    skip_body = True\n                code = start_line.code\n                if code == 304:\n                    # 304 responses may include the content-length header\n                    # but do not actually have a body.\n                    # http://tools.ietf.org/html/rfc7230#section-3.3\n                    skip_body = True\n                if code >= 100 and code < 200:\n                    # 1xx responses should never indicate the presence of\n                    # a body.\n                    if ('Content-Length' in headers or\n                            'Transfer-Encoding' in headers):\n                        raise httputil.HTTPInputError(\n                            \"Response code %d cannot have body\" % code)\n                    # TODO: client delegates will get headers_received twice\n                    # in the case of a 100-continue.  Document or change?\n                    yield self._read_message(delegate)\n            else:\n                if (headers.get(\"Expect\") == \"100-continue\" and\n                        not self._write_finished):\n                    self.stream.write(b\"HTTP/1.1 100 (Continue)\\r\\n\\r\\n\")\n            if not skip_body:\n                body_future = self._read_body(\n                    start_line.code if self.is_client else 0, headers, delegate)\n                if body_future is not None:\n                    if self._body_timeout is None:\n                        yield body_future\n                    else:\n                        try:\n                            yield gen.with_timeout(\n                                self.stream.io_loop.time() + self._body_timeout,\n                                body_future, self.stream.io_loop,\n                                quiet_exceptions=iostream.StreamClosedError)\n                        except gen.TimeoutError:\n                            gen_log.info(\"Timeout reading body from %s\",\n                                         self.context)\n                            self.stream.close()\n                            raise gen.Return(False)\n            self._read_finished = True\n            if not self._write_finished or self.is_client:\n                need_delegate_close = False\n                with _ExceptionLoggingContext(app_log):\n                    delegate.finish()\n            # If we're waiting for the application to produce an asynchronous\n            # response, and we're not detached, register a close callback\n            # on the stream (we didn't need one while we were reading)\n            if (not self._finish_future.done() and\n                    self.stream is not None and\n                    not self.stream.closed()):\n                self.stream.set_close_callback(self._on_connection_close)\n                yield self._finish_future\n            if self.is_client and self._disconnect_on_finish:\n                self.close()\n            if self.stream is None:\n                raise gen.Return(False)\n        except httputil.HTTPInputError as e:\n            gen_log.info(\"Malformed HTTP message from %s: %s\",\n                         self.context, e)\n            self.close()\n            raise gen.Return(False)\n        finally:\n            if need_delegate_close:\n                with _ExceptionLoggingContext(app_log):\n                    delegate.on_connection_close()\n            self._clear_callbacks()\n        raise gen.Return(True)\n\n    def _clear_callbacks(self):\n        \"\"\"Clears the callback attributes.\n\n        This allows the request handler to be garbage collected more\n        quickly in CPython by breaking up reference cycles.\n        \"\"\"\n        self._write_callback = None\n        self._write_future = None\n        self._close_callback = None\n        if self.stream is not None:\n            self.stream.set_close_callback(None)\n\n    def set_close_callback(self, callback):\n        \"\"\"Sets a callback that will be run when the connection is closed.\n\n        .. deprecated:: 4.0\n            Use `.HTTPMessageDelegate.on_connection_close` instead.\n        \"\"\"\n        self._close_callback = stack_context.wrap(callback)\n\n    def _on_connection_close(self):\n        # Note that this callback is only registered on the IOStream\n        # when we have finished reading the request and are waiting for\n        # the application to produce its response.\n        if self._close_callback is not None:\n            callback = self._close_callback\n            self._close_callback = None\n            callback()\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n        self._clear_callbacks()\n\n    def close(self):\n        if self.stream is not None:\n            self.stream.close()\n        self._clear_callbacks()\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n\n    def detach(self):\n        \"\"\"Take control of the underlying stream.\n\n        Returns the underlying `.IOStream` object and stops all further\n        HTTP processing.  May only be called during\n        `.HTTPMessageDelegate.headers_received`.  Intended for implementing\n        protocols like websockets that tunnel over an HTTP handshake.\n        \"\"\"\n        self._clear_callbacks()\n        stream = self.stream\n        self.stream = None\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n        return stream\n\n    def set_body_timeout(self, timeout):\n        \"\"\"Sets the body timeout for a single request.\n\n        Overrides the value from `.HTTP1ConnectionParameters`.\n        \"\"\"\n        self._body_timeout = timeout\n\n    def set_max_body_size(self, max_body_size):\n        \"\"\"Sets the body size limit for a single request.\n\n        Overrides the value from `.HTTP1ConnectionParameters`.\n        \"\"\"\n        self._max_body_size = max_body_size\n\n    def write_headers(self, start_line, headers, chunk=None, callback=None):\n        \"\"\"Implements `.HTTPConnection.write_headers`.\"\"\"\n        lines = []\n        if self.is_client:\n            self._request_start_line = start_line\n            lines.append(utf8('%s %s HTTP/1.1' % (start_line[0], start_line[1])))\n            # Client requests with a non-empty body must have either a\n            # Content-Length or a Transfer-Encoding.\n            self._chunking_output = (\n                start_line.method in ('POST', 'PUT', 'PATCH') and\n                'Content-Length' not in headers and\n                'Transfer-Encoding' not in headers)\n        else:\n            self._response_start_line = start_line\n            lines.append(utf8('HTTP/1.1 %d %s' % (start_line[1], start_line[2])))\n            self._chunking_output = (\n                # TODO: should this use\n                # self._request_start_line.version or\n                # start_line.version?\n                self._request_start_line.version == 'HTTP/1.1' and\n                # 304 responses have no body (not even a zero-length body), and so\n                # should not have either Content-Length or Transfer-Encoding.\n                # headers.\n                start_line.code not in (204, 304) and\n                # No need to chunk the output if a Content-Length is specified.\n                'Content-Length' not in headers and\n                # Applications are discouraged from touching Transfer-Encoding,\n                # but if they do, leave it alone.\n                'Transfer-Encoding' not in headers)\n            # If a 1.0 client asked for keep-alive, add the header.\n            if (self._request_start_line.version == 'HTTP/1.0' and\n                (self._request_headers.get('Connection', '').lower() ==\n                 'keep-alive')):\n                headers['Connection'] = 'Keep-Alive'\n        if self._chunking_output:\n            headers['Transfer-Encoding'] = 'chunked'\n        if (not self.is_client and\n            (self._request_start_line.method == 'HEAD' or\n             start_line.code == 304)):\n            self._expected_content_remaining = 0\n        elif 'Content-Length' in headers:\n            self._expected_content_remaining = int(headers['Content-Length'])\n        else:\n            self._expected_content_remaining = None\n        # TODO: headers are supposed to be of type str, but we still have some\n        # cases that let bytes slip through. Remove these native_str calls when those\n        # are fixed.\n        header_lines = (native_str(n) + \": \" + native_str(v) for n, v in headers.get_all())\n        if PY3:\n            lines.extend(l.encode('latin1') for l in header_lines)\n        else:\n            lines.extend(header_lines)\n        for line in lines:\n            if b'\\n' in line:\n                raise ValueError('Newline in header: ' + repr(line))\n        future = None\n        if self.stream.closed():\n            future = self._write_future = Future()\n            future.set_exception(iostream.StreamClosedError())\n            future.exception()\n        else:\n            if callback is not None:\n                self._write_callback = stack_context.wrap(callback)\n            else:\n                future = self._write_future = Future()\n            data = b\"\\r\\n\".join(lines) + b\"\\r\\n\\r\\n\"\n            if chunk:\n                data += self._format_chunk(chunk)\n            self._pending_write = self.stream.write(data)\n            self._pending_write.add_done_callback(self._on_write_complete)\n        return future\n\n    def _format_chunk(self, chunk):\n        if self._expected_content_remaining is not None:\n            self._expected_content_remaining -= len(chunk)\n            if self._expected_content_remaining < 0:\n                # Close the stream now to stop further framing errors.\n                self.stream.close()\n                raise httputil.HTTPOutputError(\n                    \"Tried to write more data than Content-Length\")\n        if self._chunking_output and chunk:\n            # Don't write out empty chunks because that means END-OF-STREAM\n            # with chunked encoding\n            return utf8(\"%x\" % len(chunk)) + b\"\\r\\n\" + chunk + b\"\\r\\n\"\n        else:\n            return chunk\n\n    def write(self, chunk, callback=None):\n        \"\"\"Implements `.HTTPConnection.write`.\n\n        For backwards compatibility is is allowed but deprecated to\n        skip `write_headers` and instead call `write()` with a\n        pre-encoded header block.\n        \"\"\"\n        future = None\n        if self.stream.closed():\n            future = self._write_future = Future()\n            self._write_future.set_exception(iostream.StreamClosedError())\n            self._write_future.exception()\n        else:\n            if callback is not None:\n                self._write_callback = stack_context.wrap(callback)\n            else:\n                future = self._write_future = Future()\n            self._pending_write = self.stream.write(self._format_chunk(chunk))\n            self._pending_write.add_done_callback(self._on_write_complete)\n        return future\n\n    def finish(self):\n        \"\"\"Implements `.HTTPConnection.finish`.\"\"\"\n        if (self._expected_content_remaining is not None and\n                self._expected_content_remaining != 0 and\n                not self.stream.closed()):\n            self.stream.close()\n            raise httputil.HTTPOutputError(\n                \"Tried to write %d bytes less than Content-Length\" %\n                self._expected_content_remaining)\n        if self._chunking_output:\n            if not self.stream.closed():\n                self._pending_write = self.stream.write(b\"0\\r\\n\\r\\n\")\n                self._pending_write.add_done_callback(self._on_write_complete)\n        self._write_finished = True\n        # If the app finished the request while we're still reading,\n        # divert any remaining data away from the delegate and\n        # close the connection when we're done sending our response.\n        # Closing the connection is the only way to avoid reading the\n        # whole input body.\n        if not self._read_finished:\n            self._disconnect_on_finish = True\n        # No more data is coming, so instruct TCP to send any remaining\n        # data immediately instead of waiting for a full packet or ack.\n        self.stream.set_nodelay(True)\n        if self._pending_write is None:\n            self._finish_request(None)\n        else:\n            self._pending_write.add_done_callback(self._finish_request)\n\n    def _on_write_complete(self, future):\n        exc = future.exception()\n        if exc is not None and not isinstance(exc, iostream.StreamClosedError):\n            future.result()\n        if self._write_callback is not None:\n            callback = self._write_callback\n            self._write_callback = None\n            self.stream.io_loop.add_callback(callback)\n        if self._write_future is not None:\n            future = self._write_future\n            self._write_future = None\n            future.set_result(None)\n\n    def _can_keep_alive(self, start_line, headers):\n        if self.params.no_keep_alive:\n            return False\n        connection_header = headers.get(\"Connection\")\n        if connection_header is not None:\n            connection_header = connection_header.lower()\n        if start_line.version == \"HTTP/1.1\":\n            return connection_header != \"close\"\n        elif (\"Content-Length\" in headers or\n              headers.get(\"Transfer-Encoding\", \"\").lower() == \"chunked\" or\n              getattr(start_line, 'method', None) in (\"HEAD\", \"GET\")):\n            # start_line may be a request or reponse start line; only\n            # the former has a method attribute.\n            return connection_header == \"keep-alive\"\n        return False\n\n    def _finish_request(self, future):\n        self._clear_callbacks()\n        if not self.is_client and self._disconnect_on_finish:\n            self.close()\n            return\n        # Turn Nagle's algorithm back on, leaving the stream in its\n        # default state for the next request.\n        self.stream.set_nodelay(False)\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n\n    def _parse_headers(self, data):\n        # The lstrip removes newlines that some implementations sometimes\n        # insert between messages of a reused connection.  Per RFC 7230,\n        # we SHOULD ignore at least one empty line before the request.\n        # http://tools.ietf.org/html/rfc7230#section-3.5\n        data = native_str(data.decode('latin1')).lstrip(\"\\r\\n\")\n        # RFC 7230 section allows for both CRLF and bare LF.\n        eol = data.find(\"\\n\")\n        start_line = data[:eol].rstrip(\"\\r\")\n        try:\n            headers = httputil.HTTPHeaders.parse(data[eol:])\n        except ValueError:\n            # probably form split() if there was no ':' in the line\n            raise httputil.HTTPInputError(\"Malformed HTTP headers: %r\" %\n                                          data[eol:100])\n        return start_line, headers\n\n    def _read_body(self, code, headers, delegate):\n        if \"Content-Length\" in headers:\n            if \"Transfer-Encoding\" in headers:\n                # Response cannot contain both Content-Length and\n                # Transfer-Encoding headers.\n                # http://tools.ietf.org/html/rfc7230#section-3.3.3\n                raise httputil.HTTPInputError(\n                    \"Response with both Transfer-Encoding and Content-Length\")\n            if \",\" in 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*', headers[\"Content-Length\"])\n                if any(i != pieces[0] for i in pieces):\n                    raise httputil.HTTPInputError(\n                        \"Multiple unequal Content-Lengths: %r\" %\n                        headers[\"Content-Length\"])\n                headers[\"Content-Length\"] = pieces[0]\n\n            try:\n                content_length = int(headers[\"Content-Length\"])\n            except ValueError:\n                # Handles non-integer Content-Length value.\n                raise httputil.HTTPInputError(\n                    \"Only integer Content-Length is allowed: %s\" % headers[\"Content-Length\"])\n\n            if content_length > self._max_body_size:\n                raise httputil.HTTPInputError(\"Content-Length too long\")\n        else:\n            content_length = None\n\n        if code == 204:\n            # This response code is not allowed to have a non-empty body,\n            # and has an implicit length of zero instead of read-until-close.\n            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3\n            if (\"Transfer-Encoding\" in headers or\n                    content_length not in (None, 0)):\n                raise httputil.HTTPInputError(\n                    \"Response with code %d should not have body\" % code)\n            content_length = 0\n\n        if content_length is not None:\n            return self._read_fixed_body(content_length, delegate)\n        if headers.get(\"Transfer-Encoding\", \"\").lower() == \"chunked\":\n            return self._read_chunked_body(delegate)\n        if self.is_client:\n            return self._read_body_until_close(delegate)\n        return None\n\n    @gen.coroutine\n    def _read_fixed_body(self, content_length, delegate):\n        while content_length > 0:\n            body = yield self.stream.read_bytes(\n                min(self.params.chunk_size, content_length), partial=True)\n            content_length -= len(body)\n            if not self._write_finished or self.is_client:\n                with _ExceptionLoggingContext(app_log):\n                    ret = delegate.data_received(body)\n                    if ret is not None:\n                        yield ret\n\n    @gen.coroutine\n    def _read_chunked_body(self, delegate):\n        # TODO: \"chunk extensions\" http://tools.ietf.org/html/rfc2616#section-3.6.1\n        total_size = 0\n        while True:\n            chunk_len = yield self.stream.read_until(b\"\\r\\n\", max_bytes=64)\n            chunk_len = int(chunk_len.strip(), 16)\n            if chunk_len == 0:\n                return\n            total_size += chunk_len\n            if total_size > self._max_body_size:\n                raise httputil.HTTPInputError(\"chunked body too large\")\n            bytes_to_read = chunk_len\n            while bytes_to_read:\n                chunk = yield self.stream.read_bytes(\n                    min(bytes_to_read, self.params.chunk_size), partial=True)\n                bytes_to_read -= len(chunk)\n                if not self._write_finished or self.is_client:\n                    with _ExceptionLoggingContext(app_log):\n                        ret = delegate.data_received(chunk)\n                        if ret is not None:\n                            yield ret\n            # chunk ends with \\r\\n\n            crlf = yield self.stream.read_bytes(2)\n            assert crlf == b\"\\r\\n\"\n\n    @gen.coroutine\n    def _read_body_until_close(self, delegate):\n        body = yield self.stream.read_until_close()\n        if not self._write_finished or self.is_client:\n            with _ExceptionLoggingContext(app_log):\n                delegate.data_received(body)\n\n\nclass _GzipMessageDelegate(httputil.HTTPMessageDelegate):\n    \"\"\"Wraps an `HTTPMessageDelegate` to decode ``Content-Encoding: gzip``.\n    \"\"\"\n    def __init__(self, delegate, chunk_size):\n        self._delegate = delegate\n        self._chunk_size = chunk_size\n        self._decompressor = None\n\n    def headers_received(self, start_line, headers):\n        if headers.get(\"Content-Encoding\") == \"gzip\":\n            self._decompressor = GzipDecompressor()\n            # Downstream delegates will only see uncompressed data,\n            # so rename the content-encoding header.\n            # (but note that curl_httpclient doesn't do this).\n            headers.add(\"X-Consumed-Content-Encoding\",\n                        headers[\"Content-Encoding\"])\n            del headers[\"Content-Encoding\"]\n        return self._delegate.headers_received(start_line, headers)\n\n    @gen.coroutine\n    def data_received(self, chunk):\n        if self._decompressor:\n            compressed_data = chunk\n            while compressed_data:\n                decompressed = self._decompressor.decompress(\n                    compressed_data, self._chunk_size)\n                if decompressed:\n                    ret = self._delegate.data_received(decompressed)\n                    if ret is not None:\n                        yield ret\n                compressed_data = self._decompressor.unconsumed_tail\n        else:\n            ret = self._delegate.data_received(chunk)\n            if ret is not None:\n                yield ret\n\n    def finish(self):\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                self._delegate.data_received(tail)\n        return self._delegate.finish()\n\n    def on_connection_close(self):\n        return self._delegate.on_connection_close()\n\n\nclass HTTP1ServerConnection(object):\n    \"\"\"An HTTP/1.x server.\"\"\"\n    def __init__(self, stream, params=None, context=None):\n        \"\"\"\n        :arg stream: an `.IOStream`\n        :arg params: a `.HTTP1ConnectionParameters` or None\n        :arg context: an opaque application-defined object that is accessible\n            as ``connection.context``\n        \"\"\"\n        self.stream = stream\n        if params is None:\n            params = HTTP1ConnectionParameters()\n        self.params = params\n        self.context = context\n        self._serving_future = None\n\n    @gen.coroutine\n    def close(self):\n        \"\"\"Closes the connection.\n\n        Returns a `.Future` that resolves after the serving loop has exited.\n        \"\"\"\n        self.stream.close()\n        # Block until the serving loop is done, but ignore any exceptions\n        # (start_serving is already responsible for logging them).\n        try:\n            yield self._serving_future\n        except Exception:\n            pass\n\n    def start_serving(self, delegate):\n        \"\"\"Starts serving requests on this connection.\n\n        :arg delegate: a `.HTTPServerConnectionDelegate`\n        \"\"\"\n        assert isinstance(delegate, httputil.HTTPServerConnectionDelegate)\n        self._serving_future = self._server_request_loop(delegate)\n        # Register the future on the IOLoop so its errors get logged.\n        self.stream.io_loop.add_future(self._serving_future,\n                                       lambda f: f.result())\n\n    @gen.coroutine\n    def _server_request_loop(self, delegate):\n        try:\n            while True:\n                conn = HTTP1Connection(self.stream, False,\n                                       self.params, self.context)\n                request_delegate = delegate.start_request(self, conn)\n                try:\n                    ret = yield conn.read_response(request_delegate)\n                except (iostream.StreamClosedError,\n                        iostream.UnsatisfiableReadError):\n                    return\n                except _QuietException:\n                    # This exception was already logged.\n                    conn.close()\n                    return\n                except Exception:\n                    gen_log.error(\"Uncaught exception\", exc_info=True)\n                    conn.close()\n                    return\n                if not ret:\n                    return\n                yield gen.moment\n        finally:\n            delegate.on_close(self)\n",
            "header": {
                "file": {
                    "path": "tornado/http1connection.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "d0e91b82",
                "new_commit_hash": "7ee83161",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tornado/http1connection.py"
            },
            "plus_file": {
                "path": "b/tornado/http1connection.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 565,
                            "length": 7
                        },
                        "new_range": {
                            "start": 565,
                            "length": 7
                        },
                        "section": "class HTTP1Connection(httputil.HTTPConnection):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        if content_length is not None:",
                                "type": "context"
                            },
                            {
                                "content": "            return self._read_fixed_body(content_length, delegate)",
                                "type": "context"
                            },
                            {
                                "content": "        if headers.get(\"Transfer-Encoding\") == \"chunked\":",
                                "type": "deleted"
                            },
                            {
                                "content": "        if headers.get(\"Transfer-Encoding\", \"\").lower() == \"chunked\":",
                                "type": "added"
                            },
                            {
                                "content": "            return self._read_chunked_body(delegate)",
                                "type": "context"
                            },
                            {
                                "content": "        if self.is_client:",
                                "type": "context"
                            },
                            {
                                "content": "            return self._read_body_until_close(delegate)",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/http1connection.py",
                            "type": "method",
                            "name": "HTTP1Connection._read_body",
                            "content": "class HTTP1Connection(httputil.HTTPConnection):\n    \"\"\"Implements the HTTP/1.x protocol.\n\n    This class can be on its own for clients, or via `HTTP1ServerConnection`\n    for servers.\n    \"\"\"\n    def __init__(self, stream, is_client, params=None, context=None):\n        \"\"\"\n        :arg stream: an `.IOStream`\n        :arg bool is_client: client or server\n        :arg params: a `.HTTP1ConnectionParameters` instance or ``None``\n        :arg context: an opaque application-defined object that can be accessed\n            as ``connection.context``.\n        \"\"\"\n        self.is_client = is_client\n        self.stream = stream\n        if params is None:\n            params = HTTP1ConnectionParameters()\n        self.params = params\n        self.context = context\n        self.no_keep_alive = params.no_keep_alive\n        # The body limits can be altered by the delegate, so save them\n        # here instead of just referencing self.params later.\n        self._max_body_size = (self.params.max_body_size or\n                               self.stream.max_buffer_size)\n        self._body_timeout = self.params.body_timeout\n        # _write_finished is set to True when finish() has been called,\n        # i.e. there will be no more data sent.  Data may still be in the\n        # stream's write buffer.\n        self._write_finished = False\n        # True when we have read the entire incoming body.\n        self._read_finished = False\n        # _finish_future resolves when all data has been written and flushed\n        # to the IOStream.\n        self._finish_future = Future()\n        # If true, the connection should be closed after this request\n        # (after the response has been written in the server side,\n        # and after it has been read in the client)\n        self._disconnect_on_finish = False\n        self._clear_callbacks()\n        # Save the start lines after we read or write them; they\n        # affect later processing (e.g. 304 responses and HEAD methods\n        # have content-length but no bodies)\n        self._request_start_line = None\n        self._response_start_line = None\n        self._request_headers = None\n        # True if we are writing output with chunked encoding.\n        self._chunking_output = None\n        # While reading a body with a content-length, this is the\n        # amount left to read.\n        self._expected_content_remaining = None\n        # A Future for our outgoing writes, returned by IOStream.write.\n        self._pending_write = None\n\n    def read_response(self, delegate):\n        \"\"\"Read a single HTTP response.\n\n        Typical client-mode usage is to write a request using `write_headers`,\n        `write`, and `finish`, and then call ``read_response``.\n\n        :arg delegate: a `.HTTPMessageDelegate`\n\n        Returns a `.Future` that resolves to None after the full response has\n        been read.\n        \"\"\"\n        if self.params.decompress:\n            delegate = _GzipMessageDelegate(delegate, self.params.chunk_size)\n        return self._read_message(delegate)\n\n    @gen.coroutine\n    def _read_message(self, delegate):\n        need_delegate_close = False\n        try:\n            header_future = self.stream.read_until_regex(\n                b\"\\r?\\n\\r?\\n\",\n                max_bytes=self.params.max_header_size)\n            if self.params.header_timeout is None:\n                header_data = yield header_future\n            else:\n                try:\n                    header_data = yield gen.with_timeout(\n                        self.stream.io_loop.time() + self.params.header_timeout,\n                        header_future,\n                        io_loop=self.stream.io_loop,\n                        quiet_exceptions=iostream.StreamClosedError)\n                except gen.TimeoutError:\n                    self.close()\n                    raise gen.Return(False)\n            start_line, headers = self._parse_headers(header_data)\n            if self.is_client:\n                start_line = httputil.parse_response_start_line(start_line)\n                self._response_start_line = start_line\n            else:\n                start_line = httputil.parse_request_start_line(start_line)\n                self._request_start_line = start_line\n                self._request_headers = headers\n\n            self._disconnect_on_finish = not self._can_keep_alive(\n                start_line, headers)\n            need_delegate_close = True\n            with _ExceptionLoggingContext(app_log):\n                header_future = delegate.headers_received(start_line, headers)\n                if header_future is not None:\n                    yield header_future\n            if self.stream is None:\n                # We've been detached.\n                need_delegate_close = False\n                raise gen.Return(False)\n            skip_body = False\n            if self.is_client:\n                if (self._request_start_line is not None and\n                        self._request_start_line.method == 'HEAD'):\n                    skip_body = True\n                code = start_line.code\n                if code == 304:\n                    # 304 responses may include the content-length header\n                    # but do not actually have a body.\n                    # http://tools.ietf.org/html/rfc7230#section-3.3\n                    skip_body = True\n                if code >= 100 and code < 200:\n                    # 1xx responses should never indicate the presence of\n                    # a body.\n                    if ('Content-Length' in headers or\n                            'Transfer-Encoding' in headers):\n                        raise httputil.HTTPInputError(\n                            \"Response code %d cannot have body\" % code)\n                    # TODO: client delegates will get headers_received twice\n                    # in the case of a 100-continue.  Document or change?\n                    yield self._read_message(delegate)\n            else:\n                if (headers.get(\"Expect\") == \"100-continue\" and\n                        not self._write_finished):\n                    self.stream.write(b\"HTTP/1.1 100 (Continue)\\r\\n\\r\\n\")\n            if not skip_body:\n                body_future = self._read_body(\n                    start_line.code if self.is_client else 0, headers, delegate)\n                if body_future is not None:\n                    if self._body_timeout is None:\n                        yield body_future\n                    else:\n                        try:\n                            yield gen.with_timeout(\n                                self.stream.io_loop.time() + self._body_timeout,\n                                body_future, self.stream.io_loop,\n                                quiet_exceptions=iostream.StreamClosedError)\n                        except gen.TimeoutError:\n                            gen_log.info(\"Timeout reading body from %s\",\n                                         self.context)\n                            self.stream.close()\n                            raise gen.Return(False)\n            self._read_finished = True\n            if not self._write_finished or self.is_client:\n                need_delegate_close = False\n                with _ExceptionLoggingContext(app_log):\n                    delegate.finish()\n            # If we're waiting for the application to produce an asynchronous\n            # response, and we're not detached, register a close callback\n            # on the stream (we didn't need one while we were reading)\n            if (not self._finish_future.done() and\n                    self.stream is not None and\n                    not self.stream.closed()):\n                self.stream.set_close_callback(self._on_connection_close)\n                yield self._finish_future\n            if self.is_client and self._disconnect_on_finish:\n                self.close()\n            if self.stream is None:\n                raise gen.Return(False)\n        except httputil.HTTPInputError as e:\n            gen_log.info(\"Malformed HTTP message from %s: %s\",\n                         self.context, e)\n            self.close()\n            raise gen.Return(False)\n        finally:\n            if need_delegate_close:\n                with _ExceptionLoggingContext(app_log):\n                    delegate.on_connection_close()\n            self._clear_callbacks()\n        raise gen.Return(True)\n\n    def _clear_callbacks(self):\n        \"\"\"Clears the callback attributes.\n\n        This allows the request handler to be garbage collected more\n        quickly in CPython by breaking up reference cycles.\n        \"\"\"\n        self._write_callback = None\n        self._write_future = None\n        self._close_callback = None\n        if self.stream is not None:\n            self.stream.set_close_callback(None)\n\n    def set_close_callback(self, callback):\n        \"\"\"Sets a callback that will be run when the connection is closed.\n\n        .. deprecated:: 4.0\n            Use `.HTTPMessageDelegate.on_connection_close` instead.\n        \"\"\"\n        self._close_callback = stack_context.wrap(callback)\n\n    def _on_connection_close(self):\n        # Note that this callback is only registered on the IOStream\n        # when we have finished reading the request and are waiting for\n        # the application to produce its response.\n        if self._close_callback is not None:\n            callback = self._close_callback\n            self._close_callback = None\n            callback()\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n        self._clear_callbacks()\n\n    def close(self):\n        if self.stream is not None:\n            self.stream.close()\n        self._clear_callbacks()\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n\n    def detach(self):\n        \"\"\"Take control of the underlying stream.\n\n        Returns the underlying `.IOStream` object and stops all further\n        HTTP processing.  May only be called during\n        `.HTTPMessageDelegate.headers_received`.  Intended for implementing\n        protocols like websockets that tunnel over an HTTP handshake.\n        \"\"\"\n        self._clear_callbacks()\n        stream = self.stream\n        self.stream = None\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n        return stream\n\n    def set_body_timeout(self, timeout):\n        \"\"\"Sets the body timeout for a single request.\n\n        Overrides the value from `.HTTP1ConnectionParameters`.\n        \"\"\"\n        self._body_timeout = timeout\n\n    def set_max_body_size(self, max_body_size):\n        \"\"\"Sets the body size limit for a single request.\n\n        Overrides the value from `.HTTP1ConnectionParameters`.\n        \"\"\"\n        self._max_body_size = max_body_size\n\n    def write_headers(self, start_line, headers, chunk=None, callback=None):\n        \"\"\"Implements `.HTTPConnection.write_headers`.\"\"\"\n        lines = []\n        if self.is_client:\n            self._request_start_line = start_line\n            lines.append(utf8('%s %s HTTP/1.1' % (start_line[0], start_line[1])))\n            # Client requests with a non-empty body must have either a\n            # Content-Length or a Transfer-Encoding.\n            self._chunking_output = (\n                start_line.method in ('POST', 'PUT', 'PATCH') and\n                'Content-Length' not in headers and\n                'Transfer-Encoding' not in headers)\n        else:\n            self._response_start_line = start_line\n            lines.append(utf8('HTTP/1.1 %d %s' % (start_line[1], start_line[2])))\n            self._chunking_output = (\n                # TODO: should this use\n                # self._request_start_line.version or\n                # start_line.version?\n                self._request_start_line.version == 'HTTP/1.1' and\n                # 304 responses have no body (not even a zero-length body), and so\n                # should not have either Content-Length or Transfer-Encoding.\n                # headers.\n                start_line.code not in (204, 304) and\n                # No need to chunk the output if a Content-Length is specified.\n                'Content-Length' not in headers and\n                # Applications are discouraged from touching Transfer-Encoding,\n                # but if they do, leave it alone.\n                'Transfer-Encoding' not in headers)\n            # If a 1.0 client asked for keep-alive, add the header.\n            if (self._request_start_line.version == 'HTTP/1.0' and\n                (self._request_headers.get('Connection', '').lower() ==\n                 'keep-alive')):\n                headers['Connection'] = 'Keep-Alive'\n        if self._chunking_output:\n            headers['Transfer-Encoding'] = 'chunked'\n        if (not self.is_client and\n            (self._request_start_line.method == 'HEAD' or\n             start_line.code == 304)):\n            self._expected_content_remaining = 0\n        elif 'Content-Length' in headers:\n            self._expected_content_remaining = int(headers['Content-Length'])\n        else:\n            self._expected_content_remaining = None\n        # TODO: headers are supposed to be of type str, but we still have some\n        # cases that let bytes slip through. Remove these native_str calls when those\n        # are fixed.\n        header_lines = (native_str(n) + \": \" + native_str(v) for n, v in headers.get_all())\n        if PY3:\n            lines.extend(l.encode('latin1') for l in header_lines)\n        else:\n            lines.extend(header_lines)\n        for line in lines:\n            if b'\\n' in line:\n                raise ValueError('Newline in header: ' + repr(line))\n        future = None\n        if self.stream.closed():\n            future = self._write_future = Future()\n            future.set_exception(iostream.StreamClosedError())\n            future.exception()\n        else:\n            if callback is not None:\n                self._write_callback = stack_context.wrap(callback)\n            else:\n                future = self._write_future = Future()\n            data = b\"\\r\\n\".join(lines) + b\"\\r\\n\\r\\n\"\n            if chunk:\n                data += self._format_chunk(chunk)\n            self._pending_write = self.stream.write(data)\n            self._pending_write.add_done_callback(self._on_write_complete)\n        return future\n\n    def _format_chunk(self, chunk):\n        if self._expected_content_remaining is not None:\n            self._expected_content_remaining -= len(chunk)\n            if self._expected_content_remaining < 0:\n                # Close the stream now to stop further framing errors.\n                self.stream.close()\n                raise httputil.HTTPOutputError(\n                    \"Tried to write more data than Content-Length\")\n        if self._chunking_output and chunk:\n            # Don't write out empty chunks because that means END-OF-STREAM\n            # with chunked encoding\n            return utf8(\"%x\" % len(chunk)) + b\"\\r\\n\" + chunk + b\"\\r\\n\"\n        else:\n            return chunk\n\n    def write(self, chunk, callback=None):\n        \"\"\"Implements `.HTTPConnection.write`.\n\n        For backwards compatibility is is allowed but deprecated to\n        skip `write_headers` and instead call `write()` with a\n        pre-encoded header block.\n        \"\"\"\n        future = None\n        if self.stream.closed():\n            future = self._write_future = Future()\n            self._write_future.set_exception(iostream.StreamClosedError())\n            self._write_future.exception()\n        else:\n            if callback is not None:\n                self._write_callback = stack_context.wrap(callback)\n            else:\n                future = self._write_future = Future()\n            self._pending_write = self.stream.write(self._format_chunk(chunk))\n            self._pending_write.add_done_callback(self._on_write_complete)\n        return future\n\n    def finish(self):\n        \"\"\"Implements `.HTTPConnection.finish`.\"\"\"\n        if (self._expected_content_remaining is not None and\n                self._expected_content_remaining != 0 and\n                not self.stream.closed()):\n            self.stream.close()\n            raise httputil.HTTPOutputError(\n                \"Tried to write %d bytes less than Content-Length\" %\n                self._expected_content_remaining)\n        if self._chunking_output:\n            if not self.stream.closed():\n                self._pending_write = self.stream.write(b\"0\\r\\n\\r\\n\")\n                self._pending_write.add_done_callback(self._on_write_complete)\n        self._write_finished = True\n        # If the app finished the request while we're still reading,\n        # divert any remaining data away from the delegate and\n        # close the connection when we're done sending our response.\n        # Closing the connection is the only way to avoid reading the\n        # whole input body.\n        if not self._read_finished:\n            self._disconnect_on_finish = True\n        # No more data is coming, so instruct TCP to send any remaining\n        # data immediately instead of waiting for a full packet or ack.\n        self.stream.set_nodelay(True)\n        if self._pending_write is None:\n            self._finish_request(None)\n        else:\n            self._pending_write.add_done_callback(self._finish_request)\n\n    def _on_write_complete(self, future):\n        exc = future.exception()\n        if exc is not None and not isinstance(exc, iostream.StreamClosedError):\n            future.result()\n        if self._write_callback is not None:\n            callback = self._write_callback\n            self._write_callback = None\n            self.stream.io_loop.add_callback(callback)\n        if self._write_future is not None:\n            future = self._write_future\n            self._write_future = None\n            future.set_result(None)\n\n    def _can_keep_alive(self, start_line, headers):\n        if self.params.no_keep_alive:\n            return False\n        connection_header = headers.get(\"Connection\")\n        if connection_header is not None:\n            connection_header = connection_header.lower()\n        if start_line.version == \"HTTP/1.1\":\n            return connection_header != \"close\"\n        elif (\"Content-Length\" in headers or\n              headers.get(\"Transfer-Encoding\", \"\").lower() == \"chunked\" or\n              getattr(start_line, 'method', None) in (\"HEAD\", \"GET\")):\n            # start_line may be a request or reponse start line; only\n            # the former has a method attribute.\n            return connection_header == \"keep-alive\"\n        return False\n\n    def _finish_request(self, future):\n        self._clear_callbacks()\n        if not self.is_client and self._disconnect_on_finish:\n            self.close()\n            return\n        # Turn Nagle's algorithm back on, leaving the stream in its\n        # default state for the next request.\n        self.stream.set_nodelay(False)\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n\n    def _parse_headers(self, data):\n        # The lstrip removes newlines that some implementations sometimes\n        # insert between messages of a reused connection.  Per RFC 7230,\n        # we SHOULD ignore at least one empty line before the request.\n        # http://tools.ietf.org/html/rfc7230#section-3.5\n        data = native_str(data.decode('latin1')).lstrip(\"\\r\\n\")\n        # RFC 7230 section allows for both CRLF and bare LF.\n        eol = data.find(\"\\n\")\n        start_line = data[:eol].rstrip(\"\\r\")\n        try:\n            headers = httputil.HTTPHeaders.parse(data[eol:])\n        except ValueError:\n            # probably form split() if there was no ':' in the line\n            raise httputil.HTTPInputError(\"Malformed HTTP headers: %r\" %\n                                          data[eol:100])\n        return start_line, headers\n\n    def _read_body(self, code, headers, delegate):\n        if \"Content-Length\" in headers:\n            if \"Transfer-Encoding\" in headers:\n                # Response cannot contain both Content-Length and\n                # Transfer-Encoding headers.\n                # http://tools.ietf.org/html/rfc7230#section-3.3.3\n                raise httputil.HTTPInputError(\n                    \"Response with both Transfer-Encoding and Content-Length\")\n            if \",\" in 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*', headers[\"Content-Length\"])\n                if any(i != pieces[0] for i in pieces):\n                    raise httputil.HTTPInputError(\n                        \"Multiple unequal Content-Lengths: %r\" %\n                        headers[\"Content-Length\"])\n                headers[\"Content-Length\"] = pieces[0]\n\n            try:\n                content_length = int(headers[\"Content-Length\"])\n            except ValueError:\n                # Handles non-integer Content-Length value.\n                raise httputil.HTTPInputError(\n                    \"Only integer Content-Length is allowed: %s\" % headers[\"Content-Length\"])\n\n            if content_length > self._max_body_size:\n                raise httputil.HTTPInputError(\"Content-Length too long\")\n        else:\n            content_length = None\n\n        if code == 204:\n            # This response code is not allowed to have a non-empty body,\n            # and has an implicit length of zero instead of read-until-close.\n            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3\n            if (\"Transfer-Encoding\" in headers or\n                    content_length not in (None, 0)):\n                raise httputil.HTTPInputError(\n                    \"Response with code %d should not have body\" % code)\n            content_length = 0\n\n        if content_length is not None:\n            return self._read_fixed_body(content_length, delegate)\n        if headers.get(\"Transfer-Encoding\") == \"chunked\":\n            return self._read_chunked_body(delegate)\n        if self.is_client:\n            return self._read_body_until_close(delegate)\n        return None\n\n    @gen.coroutine\n    def _read_fixed_body(self, content_length, delegate):\n        while content_length > 0:\n            body = yield self.stream.read_bytes(\n                min(self.params.chunk_size, content_length), partial=True)\n            content_length -= len(body)\n            if not self._write_finished or self.is_client:\n                with _ExceptionLoggingContext(app_log):\n                    ret = delegate.data_received(body)\n                    if ret is not None:\n                        yield ret\n\n    @gen.coroutine\n    def _read_chunked_body(self, delegate):\n        # TODO: \"chunk extensions\" http://tools.ietf.org/html/rfc2616#section-3.6.1\n        total_size = 0\n        while True:\n            chunk_len = yield self.stream.read_until(b\"\\r\\n\", max_bytes=64)\n            chunk_len = int(chunk_len.strip(), 16)\n            if chunk_len == 0:\n                return\n            total_size += chunk_len\n            if total_size > self._max_body_size:\n                raise httputil.HTTPInputError(\"chunked body too large\")\n            bytes_to_read = chunk_len\n            while bytes_to_read:\n                chunk = yield self.stream.read_bytes(\n                    min(bytes_to_read, self.params.chunk_size), partial=True)\n                bytes_to_read -= len(chunk)\n                if not self._write_finished or self.is_client:\n                    with _ExceptionLoggingContext(app_log):\n                        ret = delegate.data_received(chunk)\n                        if ret is not None:\n                            yield ret\n            # chunk ends with \\r\\n\n            crlf = yield self.stream.read_bytes(2)\n            assert crlf == b\"\\r\\n\"\n\n    @gen.coroutine\n    def _read_body_until_close(self, delegate):\n        body = yield self.stream.read_until_close()\n        if not self._write_finished or self.is_client:\n            with _ExceptionLoggingContext(app_log):\n                delegate.data_received(body)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 525,
                            "end_lineno": 572,
                            "parent": {
                                "file_name": "tornado/http1connection.py",
                                "type": "class",
                                "name": "HTTP1Connection",
                                "content": "class HTTP1Connection(httputil.HTTPConnection):\n    \"\"\"Implements the HTTP/1.x protocol.\n\n    This class can be on its own for clients, or via `HTTP1ServerConnection`\n    for servers.\n    \"\"\"\n    def __init__(self, stream, is_client, params=None, context=None):\n        \"\"\"\n        :arg stream: an `.IOStream`\n        :arg bool is_client: client or server\n        :arg params: a `.HTTP1ConnectionParameters` instance or ``None``\n        :arg context: an opaque application-defined object that can be accessed\n            as ``connection.context``.\n        \"\"\"\n        self.is_client = is_client\n        self.stream = stream\n        if params is None:\n            params = HTTP1ConnectionParameters()\n        self.params = params\n        self.context = context\n        self.no_keep_alive = params.no_keep_alive\n        # The body limits can be altered by the delegate, so save them\n        # here instead of just referencing self.params later.\n        self._max_body_size = (self.params.max_body_size or\n                               self.stream.max_buffer_size)\n        self._body_timeout = self.params.body_timeout\n        # _write_finished is set to True when finish() has been called,\n        # i.e. there will be no more data sent.  Data may still be in the\n        # stream's write buffer.\n        self._write_finished = False\n        # True when we have read the entire incoming body.\n        self._read_finished = False\n        # _finish_future resolves when all data has been written and flushed\n        # to the IOStream.\n        self._finish_future = Future()\n        # If true, the connection should be closed after this request\n        # (after the response has been written in the server side,\n        # and after it has been read in the client)\n        self._disconnect_on_finish = False\n        self._clear_callbacks()\n        # Save the start lines after we read or write them; they\n        # affect later processing (e.g. 304 responses and HEAD methods\n        # have content-length but no bodies)\n        self._request_start_line = None\n        self._response_start_line = None\n        self._request_headers = None\n        # True if we are writing output with chunked encoding.\n        self._chunking_output = None\n        # While reading a body with a content-length, this is the\n        # amount left to read.\n        self._expected_content_remaining = None\n        # A Future for our outgoing writes, returned by IOStream.write.\n        self._pending_write = None\n\n    def read_response(self, delegate):\n        \"\"\"Read a single HTTP response.\n\n        Typical client-mode usage is to write a request using `write_headers`,\n        `write`, and `finish`, and then call ``read_response``.\n\n        :arg delegate: a `.HTTPMessageDelegate`\n\n        Returns a `.Future` that resolves to None after the full response has\n        been read.\n        \"\"\"\n        if self.params.decompress:\n            delegate = _GzipMessageDelegate(delegate, self.params.chunk_size)\n        return self._read_message(delegate)\n\n    @gen.coroutine\n    def _read_message(self, delegate):\n        need_delegate_close = False\n        try:\n            header_future = self.stream.read_until_regex(\n                b\"\\r?\\n\\r?\\n\",\n                max_bytes=self.params.max_header_size)\n            if self.params.header_timeout is None:\n                header_data = yield header_future\n            else:\n                try:\n                    header_data = yield gen.with_timeout(\n                        self.stream.io_loop.time() + self.params.header_timeout,\n                        header_future,\n                        io_loop=self.stream.io_loop,\n                        quiet_exceptions=iostream.StreamClosedError)\n                except gen.TimeoutError:\n                    self.close()\n                    raise gen.Return(False)\n            start_line, headers = self._parse_headers(header_data)\n            if self.is_client:\n                start_line = httputil.parse_response_start_line(start_line)\n                self._response_start_line = start_line\n            else:\n                start_line = httputil.parse_request_start_line(start_line)\n                self._request_start_line = start_line\n                self._request_headers = headers\n\n            self._disconnect_on_finish = not self._can_keep_alive(\n                start_line, headers)\n            need_delegate_close = True\n            with _ExceptionLoggingContext(app_log):\n                header_future = delegate.headers_received(start_line, headers)\n                if header_future is not None:\n                    yield header_future\n            if self.stream is None:\n                # We've been detached.\n                need_delegate_close = False\n                raise gen.Return(False)\n            skip_body = False\n            if self.is_client:\n                if (self._request_start_line is not None and\n                        self._request_start_line.method == 'HEAD'):\n                    skip_body = True\n                code = start_line.code\n                if code == 304:\n                    # 304 responses may include the content-length header\n                    # but do not actually have a body.\n                    # http://tools.ietf.org/html/rfc7230#section-3.3\n                    skip_body = True\n                if code >= 100 and code < 200:\n                    # 1xx responses should never indicate the presence of\n                    # a body.\n                    if ('Content-Length' in headers or\n                            'Transfer-Encoding' in headers):\n                        raise httputil.HTTPInputError(\n                            \"Response code %d cannot have body\" % code)\n                    # TODO: client delegates will get headers_received twice\n                    # in the case of a 100-continue.  Document or change?\n                    yield self._read_message(delegate)\n            else:\n                if (headers.get(\"Expect\") == \"100-continue\" and\n                        not self._write_finished):\n                    self.stream.write(b\"HTTP/1.1 100 (Continue)\\r\\n\\r\\n\")\n            if not skip_body:\n                body_future = self._read_body(\n                    start_line.code if self.is_client else 0, headers, delegate)\n                if body_future is not None:\n                    if self._body_timeout is None:\n                        yield body_future\n                    else:\n                        try:\n                            yield gen.with_timeout(\n                                self.stream.io_loop.time() + self._body_timeout,\n                                body_future, self.stream.io_loop,\n                                quiet_exceptions=iostream.StreamClosedError)\n                        except gen.TimeoutError:\n                            gen_log.info(\"Timeout reading body from %s\",\n                                         self.context)\n                            self.stream.close()\n                            raise gen.Return(False)\n            self._read_finished = True\n            if not self._write_finished or self.is_client:\n                need_delegate_close = False\n                with _ExceptionLoggingContext(app_log):\n                    delegate.finish()\n            # If we're waiting for the application to produce an asynchronous\n            # response, and we're not detached, register a close callback\n            # on the stream (we didn't need one while we were reading)\n            if (not self._finish_future.done() and\n                    self.stream is not None and\n                    not self.stream.closed()):\n                self.stream.set_close_callback(self._on_connection_close)\n                yield self._finish_future\n            if self.is_client and self._disconnect_on_finish:\n                self.close()\n            if self.stream is None:\n                raise gen.Return(False)\n        except httputil.HTTPInputError as e:\n            gen_log.info(\"Malformed HTTP message from %s: %s\",\n                         self.context, e)\n            self.close()\n            raise gen.Return(False)\n        finally:\n            if need_delegate_close:\n                with _ExceptionLoggingContext(app_log):\n                    delegate.on_connection_close()\n            self._clear_callbacks()\n        raise gen.Return(True)\n\n    def _clear_callbacks(self):\n        \"\"\"Clears the callback attributes.\n\n        This allows the request handler to be garbage collected more\n        quickly in CPython by breaking up reference cycles.\n        \"\"\"\n        self._write_callback = None\n        self._write_future = None\n        self._close_callback = None\n        if self.stream is not None:\n            self.stream.set_close_callback(None)\n\n    def set_close_callback(self, callback):\n        \"\"\"Sets a callback that will be run when the connection is closed.\n\n        .. deprecated:: 4.0\n            Use `.HTTPMessageDelegate.on_connection_close` instead.\n        \"\"\"\n        self._close_callback = stack_context.wrap(callback)\n\n    def _on_connection_close(self):\n        # Note that this callback is only registered on the IOStream\n        # when we have finished reading the request and are waiting for\n        # the application to produce its response.\n        if self._close_callback is not None:\n            callback = self._close_callback\n            self._close_callback = None\n            callback()\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n        self._clear_callbacks()\n\n    def close(self):\n        if self.stream is not None:\n            self.stream.close()\n        self._clear_callbacks()\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n\n    def detach(self):\n        \"\"\"Take control of the underlying stream.\n\n        Returns the underlying `.IOStream` object and stops all further\n        HTTP processing.  May only be called during\n        `.HTTPMessageDelegate.headers_received`.  Intended for implementing\n        protocols like websockets that tunnel over an HTTP handshake.\n        \"\"\"\n        self._clear_callbacks()\n        stream = self.stream\n        self.stream = None\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n        return stream\n\n    def set_body_timeout(self, timeout):\n        \"\"\"Sets the body timeout for a single request.\n\n        Overrides the value from `.HTTP1ConnectionParameters`.\n        \"\"\"\n        self._body_timeout = timeout\n\n    def set_max_body_size(self, max_body_size):\n        \"\"\"Sets the body size limit for a single request.\n\n        Overrides the value from `.HTTP1ConnectionParameters`.\n        \"\"\"\n        self._max_body_size = max_body_size\n\n    def write_headers(self, start_line, headers, chunk=None, callback=None):\n        \"\"\"Implements `.HTTPConnection.write_headers`.\"\"\"\n        lines = []\n        if self.is_client:\n            self._request_start_line = start_line\n            lines.append(utf8('%s %s HTTP/1.1' % (start_line[0], start_line[1])))\n            # Client requests with a non-empty body must have either a\n            # Content-Length or a Transfer-Encoding.\n            self._chunking_output = (\n                start_line.method in ('POST', 'PUT', 'PATCH') and\n                'Content-Length' not in headers and\n                'Transfer-Encoding' not in headers)\n        else:\n            self._response_start_line = start_line\n            lines.append(utf8('HTTP/1.1 %d %s' % (start_line[1], start_line[2])))\n            self._chunking_output = (\n                # TODO: should this use\n                # self._request_start_line.version or\n                # start_line.version?\n                self._request_start_line.version == 'HTTP/1.1' and\n                # 304 responses have no body (not even a zero-length body), and so\n                # should not have either Content-Length or Transfer-Encoding.\n                # headers.\n                start_line.code not in (204, 304) and\n                # No need to chunk the output if a Content-Length is specified.\n                'Content-Length' not in headers and\n                # Applications are discouraged from touching Transfer-Encoding,\n                # but if they do, leave it alone.\n                'Transfer-Encoding' not in headers)\n            # If a 1.0 client asked for keep-alive, add the header.\n            if (self._request_start_line.version == 'HTTP/1.0' and\n                (self._request_headers.get('Connection', '').lower() ==\n                 'keep-alive')):\n                headers['Connection'] = 'Keep-Alive'\n        if self._chunking_output:\n            headers['Transfer-Encoding'] = 'chunked'\n        if (not self.is_client and\n            (self._request_start_line.method == 'HEAD' or\n             start_line.code == 304)):\n            self._expected_content_remaining = 0\n        elif 'Content-Length' in headers:\n            self._expected_content_remaining = int(headers['Content-Length'])\n        else:\n            self._expected_content_remaining = None\n        # TODO: headers are supposed to be of type str, but we still have some\n        # cases that let bytes slip through. Remove these native_str calls when those\n        # are fixed.\n        header_lines = (native_str(n) + \": \" + native_str(v) for n, v in headers.get_all())\n        if PY3:\n            lines.extend(l.encode('latin1') for l in header_lines)\n        else:\n            lines.extend(header_lines)\n        for line in lines:\n            if b'\\n' in line:\n                raise ValueError('Newline in header: ' + repr(line))\n        future = None\n        if self.stream.closed():\n            future = self._write_future = Future()\n            future.set_exception(iostream.StreamClosedError())\n            future.exception()\n        else:\n            if callback is not None:\n                self._write_callback = stack_context.wrap(callback)\n            else:\n                future = self._write_future = Future()\n            data = b\"\\r\\n\".join(lines) + b\"\\r\\n\\r\\n\"\n            if chunk:\n                data += self._format_chunk(chunk)\n            self._pending_write = self.stream.write(data)\n            self._pending_write.add_done_callback(self._on_write_complete)\n        return future\n\n    def _format_chunk(self, chunk):\n        if self._expected_content_remaining is not None:\n            self._expected_content_remaining -= len(chunk)\n            if self._expected_content_remaining < 0:\n                # Close the stream now to stop further framing errors.\n                self.stream.close()\n                raise httputil.HTTPOutputError(\n                    \"Tried to write more data than Content-Length\")\n        if self._chunking_output and chunk:\n            # Don't write out empty chunks because that means END-OF-STREAM\n            # with chunked encoding\n            return utf8(\"%x\" % len(chunk)) + b\"\\r\\n\" + chunk + b\"\\r\\n\"\n        else:\n            return chunk\n\n    def write(self, chunk, callback=None):\n        \"\"\"Implements `.HTTPConnection.write`.\n\n        For backwards compatibility is is allowed but deprecated to\n        skip `write_headers` and instead call `write()` with a\n        pre-encoded header block.\n        \"\"\"\n        future = None\n        if self.stream.closed():\n            future = self._write_future = Future()\n            self._write_future.set_exception(iostream.StreamClosedError())\n            self._write_future.exception()\n        else:\n            if callback is not None:\n                self._write_callback = stack_context.wrap(callback)\n            else:\n                future = self._write_future = Future()\n            self._pending_write = self.stream.write(self._format_chunk(chunk))\n            self._pending_write.add_done_callback(self._on_write_complete)\n        return future\n\n    def finish(self):\n        \"\"\"Implements `.HTTPConnection.finish`.\"\"\"\n        if (self._expected_content_remaining is not None and\n                self._expected_content_remaining != 0 and\n                not self.stream.closed()):\n            self.stream.close()\n            raise httputil.HTTPOutputError(\n                \"Tried to write %d bytes less than Content-Length\" %\n                self._expected_content_remaining)\n        if self._chunking_output:\n            if not self.stream.closed():\n                self._pending_write = self.stream.write(b\"0\\r\\n\\r\\n\")\n                self._pending_write.add_done_callback(self._on_write_complete)\n        self._write_finished = True\n        # If the app finished the request while we're still reading,\n        # divert any remaining data away from the delegate and\n        # close the connection when we're done sending our response.\n        # Closing the connection is the only way to avoid reading the\n        # whole input body.\n        if not self._read_finished:\n            self._disconnect_on_finish = True\n        # No more data is coming, so instruct TCP to send any remaining\n        # data immediately instead of waiting for a full packet or ack.\n        self.stream.set_nodelay(True)\n        if self._pending_write is None:\n            self._finish_request(None)\n        else:\n            self._pending_write.add_done_callback(self._finish_request)\n\n    def _on_write_complete(self, future):\n        exc = future.exception()\n        if exc is not None and not isinstance(exc, iostream.StreamClosedError):\n            future.result()\n        if self._write_callback is not None:\n            callback = self._write_callback\n            self._write_callback = None\n            self.stream.io_loop.add_callback(callback)\n        if self._write_future is not None:\n            future = self._write_future\n            self._write_future = None\n            future.set_result(None)\n\n    def _can_keep_alive(self, start_line, headers):\n        if self.params.no_keep_alive:\n            return False\n        connection_header = headers.get(\"Connection\")\n        if connection_header is not None:\n            connection_header = connection_header.lower()\n        if start_line.version == \"HTTP/1.1\":\n            return connection_header != \"close\"\n        elif (\"Content-Length\" in headers or\n              headers.get(\"Transfer-Encoding\", \"\").lower() == \"chunked\" or\n              getattr(start_line, 'method', None) in (\"HEAD\", \"GET\")):\n            # start_line may be a request or reponse start line; only\n            # the former has a method attribute.\n            return connection_header == \"keep-alive\"\n        return False\n\n    def _finish_request(self, future):\n        self._clear_callbacks()\n        if not self.is_client and self._disconnect_on_finish:\n            self.close()\n            return\n        # Turn Nagle's algorithm back on, leaving the stream in its\n        # default state for the next request.\n        self.stream.set_nodelay(False)\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n\n    def _parse_headers(self, data):\n        # The lstrip removes newlines that some implementations sometimes\n        # insert between messages of a reused connection.  Per RFC 7230,\n        # we SHOULD ignore at least one empty line before the request.\n        # http://tools.ietf.org/html/rfc7230#section-3.5\n        data = native_str(data.decode('latin1')).lstrip(\"\\r\\n\")\n        # RFC 7230 section allows for both CRLF and bare LF.\n        eol = data.find(\"\\n\")\n        start_line = data[:eol].rstrip(\"\\r\")\n        try:\n            headers = httputil.HTTPHeaders.parse(data[eol:])\n        except ValueError:\n            # probably form split() if there was no ':' in the line\n            raise httputil.HTTPInputError(\"Malformed HTTP headers: %r\" %\n                                          data[eol:100])\n        return start_line, headers\n\n    def _read_body(self, code, headers, delegate):\n        if \"Content-Length\" in headers:\n            if \"Transfer-Encoding\" in headers:\n                # Response cannot contain both Content-Length and\n                # Transfer-Encoding headers.\n                # http://tools.ietf.org/html/rfc7230#section-3.3.3\n                raise httputil.HTTPInputError(\n                    \"Response with both Transfer-Encoding and Content-Length\")\n            if \",\" in 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*', headers[\"Content-Length\"])\n                if any(i != pieces[0] for i in pieces):\n                    raise httputil.HTTPInputError(\n                        \"Multiple unequal Content-Lengths: %r\" %\n                        headers[\"Content-Length\"])\n                headers[\"Content-Length\"] = pieces[0]\n\n            try:\n                content_length = int(headers[\"Content-Length\"])\n            except ValueError:\n                # Handles non-integer Content-Length value.\n                raise httputil.HTTPInputError(\n                    \"Only integer Content-Length is allowed: %s\" % headers[\"Content-Length\"])\n\n            if content_length > self._max_body_size:\n                raise httputil.HTTPInputError(\"Content-Length too long\")\n        else:\n            content_length = None\n\n        if code == 204:\n            # This response code is not allowed to have a non-empty body,\n            # and has an implicit length of zero instead of read-until-close.\n            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3\n            if (\"Transfer-Encoding\" in headers or\n                    content_length not in (None, 0)):\n                raise httputil.HTTPInputError(\n                    \"Response with code %d should not have body\" % code)\n            content_length = 0\n\n        if content_length is not None:\n            return self._read_fixed_body(content_length, delegate)\n        if headers.get(\"Transfer-Encoding\") == \"chunked\":\n            return self._read_chunked_body(delegate)\n        if self.is_client:\n            return self._read_body_until_close(delegate)\n        return None\n\n    @gen.coroutine\n    def _read_fixed_body(self, content_length, delegate):\n        while content_length > 0:\n            body = yield self.stream.read_bytes(\n                min(self.params.chunk_size, content_length), partial=True)\n            content_length -= len(body)\n            if not self._write_finished or self.is_client:\n                with _ExceptionLoggingContext(app_log):\n                    ret = delegate.data_received(body)\n                    if ret is not None:\n                        yield ret\n\n    @gen.coroutine\n    def _read_chunked_body(self, delegate):\n        # TODO: \"chunk extensions\" http://tools.ietf.org/html/rfc2616#section-3.6.1\n        total_size = 0\n        while True:\n            chunk_len = yield self.stream.read_until(b\"\\r\\n\", max_bytes=64)\n            chunk_len = int(chunk_len.strip(), 16)\n            if chunk_len == 0:\n                return\n            total_size += chunk_len\n            if total_size > self._max_body_size:\n                raise httputil.HTTPInputError(\"chunked body too large\")\n            bytes_to_read = chunk_len\n            while bytes_to_read:\n                chunk = yield self.stream.read_bytes(\n                    min(bytes_to_read, self.params.chunk_size), partial=True)\n                bytes_to_read -= len(chunk)\n                if not self._write_finished or self.is_client:\n                    with _ExceptionLoggingContext(app_log):\n                        ret = delegate.data_received(chunk)\n                        if ret is not None:\n                            yield ret\n            # chunk ends with \\r\\n\n            crlf = yield self.stream.read_bytes(2)\n            assert crlf == b\"\\r\\n\"\n\n    @gen.coroutine\n    def _read_body_until_close(self, delegate):\n        body = yield self.stream.read_until_close()\n        if not self._write_finished or self.is_client:\n            with _ExceptionLoggingContext(app_log):\n                delegate.data_received(body)",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 84,
                                "end_lineno": 617,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "tornado/http1connection.py",
                            "type": "class",
                            "name": "HTTP1Connection",
                            "content": "class HTTP1Connection(httputil.HTTPConnection):\n    \"\"\"Implements the HTTP/1.x protocol.\n\n    This class can be on its own for clients, or via `HTTP1ServerConnection`\n    for servers.\n    \"\"\"\n    def __init__(self, stream, is_client, params=None, context=None):\n        \"\"\"\n        :arg stream: an `.IOStream`\n        :arg bool is_client: client or server\n        :arg params: a `.HTTP1ConnectionParameters` instance or ``None``\n        :arg context: an opaque application-defined object that can be accessed\n            as ``connection.context``.\n        \"\"\"\n        self.is_client = is_client\n        self.stream = stream\n        if params is None:\n            params = HTTP1ConnectionParameters()\n        self.params = params\n        self.context = context\n        self.no_keep_alive = params.no_keep_alive\n        # The body limits can be altered by the delegate, so save them\n        # here instead of just referencing self.params later.\n        self._max_body_size = (self.params.max_body_size or\n                               self.stream.max_buffer_size)\n        self._body_timeout = self.params.body_timeout\n        # _write_finished is set to True when finish() has been called,\n        # i.e. there will be no more data sent.  Data may still be in the\n        # stream's write buffer.\n        self._write_finished = False\n        # True when we have read the entire incoming body.\n        self._read_finished = False\n        # _finish_future resolves when all data has been written and flushed\n        # to the IOStream.\n        self._finish_future = Future()\n        # If true, the connection should be closed after this request\n        # (after the response has been written in the server side,\n        # and after it has been read in the client)\n        self._disconnect_on_finish = False\n        self._clear_callbacks()\n        # Save the start lines after we read or write them; they\n        # affect later processing (e.g. 304 responses and HEAD methods\n        # have content-length but no bodies)\n        self._request_start_line = None\n        self._response_start_line = None\n        self._request_headers = None\n        # True if we are writing output with chunked encoding.\n        self._chunking_output = None\n        # While reading a body with a content-length, this is the\n        # amount left to read.\n        self._expected_content_remaining = None\n        # A Future for our outgoing writes, returned by IOStream.write.\n        self._pending_write = None\n\n    def read_response(self, delegate):\n        \"\"\"Read a single HTTP response.\n\n        Typical client-mode usage is to write a request using `write_headers`,\n        `write`, and `finish`, and then call ``read_response``.\n\n        :arg delegate: a `.HTTPMessageDelegate`\n\n        Returns a `.Future` that resolves to None after the full response has\n        been read.\n        \"\"\"\n        if self.params.decompress:\n            delegate = _GzipMessageDelegate(delegate, self.params.chunk_size)\n        return self._read_message(delegate)\n\n    @gen.coroutine\n    def _read_message(self, delegate):\n        need_delegate_close = False\n        try:\n            header_future = self.stream.read_until_regex(\n                b\"\\r?\\n\\r?\\n\",\n                max_bytes=self.params.max_header_size)\n            if self.params.header_timeout is None:\n                header_data = yield header_future\n            else:\n                try:\n                    header_data = yield gen.with_timeout(\n                        self.stream.io_loop.time() + self.params.header_timeout,\n                        header_future,\n                        io_loop=self.stream.io_loop,\n                        quiet_exceptions=iostream.StreamClosedError)\n                except gen.TimeoutError:\n                    self.close()\n                    raise gen.Return(False)\n            start_line, headers = self._parse_headers(header_data)\n            if self.is_client:\n                start_line = httputil.parse_response_start_line(start_line)\n                self._response_start_line = start_line\n            else:\n                start_line = httputil.parse_request_start_line(start_line)\n                self._request_start_line = start_line\n                self._request_headers = headers\n\n            self._disconnect_on_finish = not self._can_keep_alive(\n                start_line, headers)\n            need_delegate_close = True\n            with _ExceptionLoggingContext(app_log):\n                header_future = delegate.headers_received(start_line, headers)\n                if header_future is not None:\n                    yield header_future\n            if self.stream is None:\n                # We've been detached.\n                need_delegate_close = False\n                raise gen.Return(False)\n            skip_body = False\n            if self.is_client:\n                if (self._request_start_line is not None and\n                        self._request_start_line.method == 'HEAD'):\n                    skip_body = True\n                code = start_line.code\n                if code == 304:\n                    # 304 responses may include the content-length header\n                    # but do not actually have a body.\n                    # http://tools.ietf.org/html/rfc7230#section-3.3\n                    skip_body = True\n                if code >= 100 and code < 200:\n                    # 1xx responses should never indicate the presence of\n                    # a body.\n                    if ('Content-Length' in headers or\n                            'Transfer-Encoding' in headers):\n                        raise httputil.HTTPInputError(\n                            \"Response code %d cannot have body\" % code)\n                    # TODO: client delegates will get headers_received twice\n                    # in the case of a 100-continue.  Document or change?\n                    yield self._read_message(delegate)\n            else:\n                if (headers.get(\"Expect\") == \"100-continue\" and\n                        not self._write_finished):\n                    self.stream.write(b\"HTTP/1.1 100 (Continue)\\r\\n\\r\\n\")\n            if not skip_body:\n                body_future = self._read_body(\n                    start_line.code if self.is_client else 0, headers, delegate)\n                if body_future is not None:\n                    if self._body_timeout is None:\n                        yield body_future\n                    else:\n                        try:\n                            yield gen.with_timeout(\n                                self.stream.io_loop.time() + self._body_timeout,\n                                body_future, self.stream.io_loop,\n                                quiet_exceptions=iostream.StreamClosedError)\n                        except gen.TimeoutError:\n                            gen_log.info(\"Timeout reading body from %s\",\n                                         self.context)\n                            self.stream.close()\n                            raise gen.Return(False)\n            self._read_finished = True\n            if not self._write_finished or self.is_client:\n                need_delegate_close = False\n                with _ExceptionLoggingContext(app_log):\n                    delegate.finish()\n            # If we're waiting for the application to produce an asynchronous\n            # response, and we're not detached, register a close callback\n            # on the stream (we didn't need one while we were reading)\n            if (not self._finish_future.done() and\n                    self.stream is not None and\n                    not self.stream.closed()):\n                self.stream.set_close_callback(self._on_connection_close)\n                yield self._finish_future\n            if self.is_client and self._disconnect_on_finish:\n                self.close()\n            if self.stream is None:\n                raise gen.Return(False)\n        except httputil.HTTPInputError as e:\n            gen_log.info(\"Malformed HTTP message from %s: %s\",\n                         self.context, e)\n            self.close()\n            raise gen.Return(False)\n        finally:\n            if need_delegate_close:\n                with _ExceptionLoggingContext(app_log):\n                    delegate.on_connection_close()\n            self._clear_callbacks()\n        raise gen.Return(True)\n\n    def _clear_callbacks(self):\n        \"\"\"Clears the callback attributes.\n\n        This allows the request handler to be garbage collected more\n        quickly in CPython by breaking up reference cycles.\n        \"\"\"\n        self._write_callback = None\n        self._write_future = None\n        self._close_callback = None\n        if self.stream is not None:\n            self.stream.set_close_callback(None)\n\n    def set_close_callback(self, callback):\n        \"\"\"Sets a callback that will be run when the connection is closed.\n\n        .. deprecated:: 4.0\n            Use `.HTTPMessageDelegate.on_connection_close` instead.\n        \"\"\"\n        self._close_callback = stack_context.wrap(callback)\n\n    def _on_connection_close(self):\n        # Note that this callback is only registered on the IOStream\n        # when we have finished reading the request and are waiting for\n        # the application to produce its response.\n        if self._close_callback is not None:\n            callback = self._close_callback\n            self._close_callback = None\n            callback()\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n        self._clear_callbacks()\n\n    def close(self):\n        if self.stream is not None:\n            self.stream.close()\n        self._clear_callbacks()\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n\n    def detach(self):\n        \"\"\"Take control of the underlying stream.\n\n        Returns the underlying `.IOStream` object and stops all further\n        HTTP processing.  May only be called during\n        `.HTTPMessageDelegate.headers_received`.  Intended for implementing\n        protocols like websockets that tunnel over an HTTP handshake.\n        \"\"\"\n        self._clear_callbacks()\n        stream = self.stream\n        self.stream = None\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n        return stream\n\n    def set_body_timeout(self, timeout):\n        \"\"\"Sets the body timeout for a single request.\n\n        Overrides the value from `.HTTP1ConnectionParameters`.\n        \"\"\"\n        self._body_timeout = timeout\n\n    def set_max_body_size(self, max_body_size):\n        \"\"\"Sets the body size limit for a single request.\n\n        Overrides the value from `.HTTP1ConnectionParameters`.\n        \"\"\"\n        self._max_body_size = max_body_size\n\n    def write_headers(self, start_line, headers, chunk=None, callback=None):\n        \"\"\"Implements `.HTTPConnection.write_headers`.\"\"\"\n        lines = []\n        if self.is_client:\n            self._request_start_line = start_line\n            lines.append(utf8('%s %s HTTP/1.1' % (start_line[0], start_line[1])))\n            # Client requests with a non-empty body must have either a\n            # Content-Length or a Transfer-Encoding.\n            self._chunking_output = (\n                start_line.method in ('POST', 'PUT', 'PATCH') and\n                'Content-Length' not in headers and\n                'Transfer-Encoding' not in headers)\n        else:\n            self._response_start_line = start_line\n            lines.append(utf8('HTTP/1.1 %d %s' % (start_line[1], start_line[2])))\n            self._chunking_output = (\n                # TODO: should this use\n                # self._request_start_line.version or\n                # start_line.version?\n                self._request_start_line.version == 'HTTP/1.1' and\n                # 304 responses have no body (not even a zero-length body), and so\n                # should not have either Content-Length or Transfer-Encoding.\n                # headers.\n                start_line.code not in (204, 304) and\n                # No need to chunk the output if a Content-Length is specified.\n                'Content-Length' not in headers and\n                # Applications are discouraged from touching Transfer-Encoding,\n                # but if they do, leave it alone.\n                'Transfer-Encoding' not in headers)\n            # If a 1.0 client asked for keep-alive, add the header.\n            if (self._request_start_line.version == 'HTTP/1.0' and\n                (self._request_headers.get('Connection', '').lower() ==\n                 'keep-alive')):\n                headers['Connection'] = 'Keep-Alive'\n        if self._chunking_output:\n            headers['Transfer-Encoding'] = 'chunked'\n        if (not self.is_client and\n            (self._request_start_line.method == 'HEAD' or\n             start_line.code == 304)):\n            self._expected_content_remaining = 0\n        elif 'Content-Length' in headers:\n            self._expected_content_remaining = int(headers['Content-Length'])\n        else:\n            self._expected_content_remaining = None\n        # TODO: headers are supposed to be of type str, but we still have some\n        # cases that let bytes slip through. Remove these native_str calls when those\n        # are fixed.\n        header_lines = (native_str(n) + \": \" + native_str(v) for n, v in headers.get_all())\n        if PY3:\n            lines.extend(l.encode('latin1') for l in header_lines)\n        else:\n            lines.extend(header_lines)\n        for line in lines:\n            if b'\\n' in line:\n                raise ValueError('Newline in header: ' + repr(line))\n        future = None\n        if self.stream.closed():\n            future = self._write_future = Future()\n            future.set_exception(iostream.StreamClosedError())\n            future.exception()\n        else:\n            if callback is not None:\n                self._write_callback = stack_context.wrap(callback)\n            else:\n                future = self._write_future = Future()\n            data = b\"\\r\\n\".join(lines) + b\"\\r\\n\\r\\n\"\n            if chunk:\n                data += self._format_chunk(chunk)\n            self._pending_write = self.stream.write(data)\n            self._pending_write.add_done_callback(self._on_write_complete)\n        return future\n\n    def _format_chunk(self, chunk):\n        if self._expected_content_remaining is not None:\n            self._expected_content_remaining -= len(chunk)\n            if self._expected_content_remaining < 0:\n                # Close the stream now to stop further framing errors.\n                self.stream.close()\n                raise httputil.HTTPOutputError(\n                    \"Tried to write more data than Content-Length\")\n        if self._chunking_output and chunk:\n            # Don't write out empty chunks because that means END-OF-STREAM\n            # with chunked encoding\n            return utf8(\"%x\" % len(chunk)) + b\"\\r\\n\" + chunk + b\"\\r\\n\"\n        else:\n            return chunk\n\n    def write(self, chunk, callback=None):\n        \"\"\"Implements `.HTTPConnection.write`.\n\n        For backwards compatibility is is allowed but deprecated to\n        skip `write_headers` and instead call `write()` with a\n        pre-encoded header block.\n        \"\"\"\n        future = None\n        if self.stream.closed():\n            future = self._write_future = Future()\n            self._write_future.set_exception(iostream.StreamClosedError())\n            self._write_future.exception()\n        else:\n            if callback is not None:\n                self._write_callback = stack_context.wrap(callback)\n            else:\n                future = self._write_future = Future()\n            self._pending_write = self.stream.write(self._format_chunk(chunk))\n            self._pending_write.add_done_callback(self._on_write_complete)\n        return future\n\n    def finish(self):\n        \"\"\"Implements `.HTTPConnection.finish`.\"\"\"\n        if (self._expected_content_remaining is not None and\n                self._expected_content_remaining != 0 and\n                not self.stream.closed()):\n            self.stream.close()\n            raise httputil.HTTPOutputError(\n                \"Tried to write %d bytes less than Content-Length\" %\n                self._expected_content_remaining)\n        if self._chunking_output:\n            if not self.stream.closed():\n                self._pending_write = self.stream.write(b\"0\\r\\n\\r\\n\")\n                self._pending_write.add_done_callback(self._on_write_complete)\n        self._write_finished = True\n        # If the app finished the request while we're still reading,\n        # divert any remaining data away from the delegate and\n        # close the connection when we're done sending our response.\n        # Closing the connection is the only way to avoid reading the\n        # whole input body.\n        if not self._read_finished:\n            self._disconnect_on_finish = True\n        # No more data is coming, so instruct TCP to send any remaining\n        # data immediately instead of waiting for a full packet or ack.\n        self.stream.set_nodelay(True)\n        if self._pending_write is None:\n            self._finish_request(None)\n        else:\n            self._pending_write.add_done_callback(self._finish_request)\n\n    def _on_write_complete(self, future):\n        exc = future.exception()\n        if exc is not None and not isinstance(exc, iostream.StreamClosedError):\n            future.result()\n        if self._write_callback is not None:\n            callback = self._write_callback\n            self._write_callback = None\n            self.stream.io_loop.add_callback(callback)\n        if self._write_future is not None:\n            future = self._write_future\n            self._write_future = None\n            future.set_result(None)\n\n    def _can_keep_alive(self, start_line, headers):\n        if self.params.no_keep_alive:\n            return False\n        connection_header = headers.get(\"Connection\")\n        if connection_header is not None:\n            connection_header = connection_header.lower()\n        if start_line.version == \"HTTP/1.1\":\n            return connection_header != \"close\"\n        elif (\"Content-Length\" in headers or\n              headers.get(\"Transfer-Encoding\", \"\").lower() == \"chunked\" or\n              getattr(start_line, 'method', None) in (\"HEAD\", \"GET\")):\n            # start_line may be a request or reponse start line; only\n            # the former has a method attribute.\n            return connection_header == \"keep-alive\"\n        return False\n\n    def _finish_request(self, future):\n        self._clear_callbacks()\n        if not self.is_client and self._disconnect_on_finish:\n            self.close()\n            return\n        # Turn Nagle's algorithm back on, leaving the stream in its\n        # default state for the next request.\n        self.stream.set_nodelay(False)\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n\n    def _parse_headers(self, data):\n        # The lstrip removes newlines that some implementations sometimes\n        # insert between messages of a reused connection.  Per RFC 7230,\n        # we SHOULD ignore at least one empty line before the request.\n        # http://tools.ietf.org/html/rfc7230#section-3.5\n        data = native_str(data.decode('latin1')).lstrip(\"\\r\\n\")\n        # RFC 7230 section allows for both CRLF and bare LF.\n        eol = data.find(\"\\n\")\n        start_line = data[:eol].rstrip(\"\\r\")\n        try:\n            headers = httputil.HTTPHeaders.parse(data[eol:])\n        except ValueError:\n            # probably form split() if there was no ':' in the line\n            raise httputil.HTTPInputError(\"Malformed HTTP headers: %r\" %\n                                          data[eol:100])\n        return start_line, headers\n\n    def _read_body(self, code, headers, delegate):\n        if \"Content-Length\" in headers:\n            if \"Transfer-Encoding\" in headers:\n                # Response cannot contain both Content-Length and\n                # Transfer-Encoding headers.\n                # http://tools.ietf.org/html/rfc7230#section-3.3.3\n                raise httputil.HTTPInputError(\n                    \"Response with both Transfer-Encoding and Content-Length\")\n            if \",\" in 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*', headers[\"Content-Length\"])\n                if any(i != pieces[0] for i in pieces):\n                    raise httputil.HTTPInputError(\n                        \"Multiple unequal Content-Lengths: %r\" %\n                        headers[\"Content-Length\"])\n                headers[\"Content-Length\"] = pieces[0]\n\n            try:\n                content_length = int(headers[\"Content-Length\"])\n            except ValueError:\n                # Handles non-integer Content-Length value.\n                raise httputil.HTTPInputError(\n                    \"Only integer Content-Length is allowed: %s\" % headers[\"Content-Length\"])\n\n            if content_length > self._max_body_size:\n                raise httputil.HTTPInputError(\"Content-Length too long\")\n        else:\n            content_length = None\n\n        if code == 204:\n            # This response code is not allowed to have a non-empty body,\n            # and has an implicit length of zero instead of read-until-close.\n            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3\n            if (\"Transfer-Encoding\" in headers or\n                    content_length not in (None, 0)):\n                raise httputil.HTTPInputError(\n                    \"Response with code %d should not have body\" % code)\n            content_length = 0\n\n        if content_length is not None:\n            return self._read_fixed_body(content_length, delegate)\n        if headers.get(\"Transfer-Encoding\") == \"chunked\":\n            return self._read_chunked_body(delegate)\n        if self.is_client:\n            return self._read_body_until_close(delegate)\n        return None\n\n    @gen.coroutine\n    def _read_fixed_body(self, content_length, delegate):\n        while content_length > 0:\n            body = yield self.stream.read_bytes(\n                min(self.params.chunk_size, content_length), partial=True)\n            content_length -= len(body)\n            if not self._write_finished or self.is_client:\n                with _ExceptionLoggingContext(app_log):\n                    ret = delegate.data_received(body)\n                    if ret is not None:\n                        yield ret\n\n    @gen.coroutine\n    def _read_chunked_body(self, delegate):\n        # TODO: \"chunk extensions\" http://tools.ietf.org/html/rfc2616#section-3.6.1\n        total_size = 0\n        while True:\n            chunk_len = yield self.stream.read_until(b\"\\r\\n\", max_bytes=64)\n            chunk_len = int(chunk_len.strip(), 16)\n            if chunk_len == 0:\n                return\n            total_size += chunk_len\n            if total_size > self._max_body_size:\n                raise httputil.HTTPInputError(\"chunked body too large\")\n            bytes_to_read = chunk_len\n            while bytes_to_read:\n                chunk = yield self.stream.read_bytes(\n                    min(bytes_to_read, self.params.chunk_size), partial=True)\n                bytes_to_read -= len(chunk)\n                if not self._write_finished or self.is_client:\n                    with _ExceptionLoggingContext(app_log):\n                        ret = delegate.data_received(chunk)\n                        if ret is not None:\n                            yield ret\n            # chunk ends with \\r\\n\n            crlf = yield self.stream.read_bytes(2)\n            assert crlf == b\"\\r\\n\"\n\n    @gen.coroutine\n    def _read_body_until_close(self, delegate):\n        body = yield self.stream.read_until_close()\n        if not self._write_finished or self.is_client:\n            with _ExceptionLoggingContext(app_log):\n                delegate.data_received(body)",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 84,
                            "end_lineno": 617,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "#!/usr/bin/env python\n\n\nfrom __future__ import absolute_import, division, print_function, with_statement\nfrom tornado import netutil\nfrom tornado.escape import json_decode, json_encode, utf8, _unicode, recursive_unicode, native_str\nfrom tornado import gen\nfrom tornado.http1connection import HTTP1Connection\nfrom tornado.httpserver import HTTPServer\nfrom tornado.httputil import HTTPHeaders, HTTPMessageDelegate, HTTPServerConnectionDelegate, ResponseStartLine\nfrom tornado.iostream import IOStream\nfrom tornado.log import gen_log\nfrom tornado.netutil import ssl_options_to_context\nfrom tornado.simple_httpclient import SimpleAsyncHTTPClient\nfrom tornado.testing import AsyncHTTPTestCase, AsyncHTTPSTestCase, AsyncTestCase, ExpectLog, gen_test\nfrom tornado.test.util import unittest, skipOnTravis\nfrom tornado.web import Application, RequestHandler, asynchronous, stream_request_body\nfrom contextlib import closing\nimport datetime\nimport gzip\nimport os\nimport shutil\nimport socket\nimport ssl\nimport sys\nimport tempfile\nfrom io import BytesIO\n\n\ndef read_stream_body(stream, callback):\n    \"\"\"Reads an HTTP response from `stream` and runs callback with its\n    headers and body.\"\"\"\n    chunks = []\n\n    class Delegate(HTTPMessageDelegate):\n        def headers_received(self, start_line, headers):\n            self.headers = headers\n\n        def data_received(self, chunk):\n            chunks.append(chunk)\n\n        def finish(self):\n            callback((self.headers, b''.join(chunks)))\n    conn = HTTP1Connection(stream, True)\n    conn.read_response(Delegate())\n\n\nclass HandlerBaseTestCase(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([('/', self.__class__.Handler)])\n\n    def fetch_json(self, *args, **kwargs):\n        response = self.fetch(*args, **kwargs)\n        response.rethrow()\n        return json_decode(response.body)\n\n\nclass HelloWorldRequestHandler(RequestHandler):\n    def initialize(self, protocol=\"http\"):\n        self.expected_protocol = protocol\n\n    def get(self):\n        if self.request.protocol != self.expected_protocol:\n            raise Exception(\"unexpected protocol\")\n        self.finish(\"Hello world\")\n\n    def post(self):\n        self.finish(\"Got %d bytes in POST\" % len(self.request.body))\n\n\n# In pre-1.0 versions of openssl, SSLv23 clients always send SSLv2\n# ClientHello messages, which are rejected by SSLv3 and TLSv1\n# servers.  Note that while the OPENSSL_VERSION_INFO was formally\n# introduced in python3.2, it was present but undocumented in\n# python 2.7\nskipIfOldSSL = unittest.skipIf(\n    getattr(ssl, 'OPENSSL_VERSION_INFO', (0, 0)) < (1, 0),\n    \"old version of ssl module and/or openssl\")\n\n\nclass BaseSSLTest(AsyncHTTPSTestCase):\n    def get_app(self):\n        return Application([('/', HelloWorldRequestHandler,\n                             dict(protocol=\"https\"))])\n\n\nclass SSLTestMixin(object):\n    def get_ssl_options(self):\n        return dict(ssl_version=self.get_ssl_version(),  # type: ignore\n                    **AsyncHTTPSTestCase.get_ssl_options())\n\n    def get_ssl_version(self):\n        raise NotImplementedError()\n\n    def test_ssl(self):\n        response = self.fetch('/')\n        self.assertEqual(response.body, b\"Hello world\")\n\n    def test_large_post(self):\n        response = self.fetch('/',\n                              method='POST',\n                              body='A' * 5000)\n        self.assertEqual(response.body, b\"Got 5000 bytes in POST\")\n\n    def test_non_ssl_request(self):\n        # Make sure the server closes the connection when it gets a non-ssl\n        # connection, rather than waiting for a timeout or otherwise\n        # misbehaving.\n        with ExpectLog(gen_log, '(SSL Error|uncaught exception)'):\n            with ExpectLog(gen_log, 'Uncaught exception', required=False):\n                self.http_client.fetch(\n                    self.get_url(\"/\").replace('https:', 'http:'),\n                    self.stop,\n                    request_timeout=3600,\n                    connect_timeout=3600)\n                response = self.wait()\n        self.assertEqual(response.code, 599)\n\n    def test_error_logging(self):\n        # No stack traces are logged for SSL errors.\n        with ExpectLog(gen_log, 'SSL Error') as expect_log:\n            self.http_client.fetch(\n                self.get_url(\"/\").replace(\"https:\", \"http:\"),\n                self.stop)\n            response = self.wait()\n            self.assertEqual(response.code, 599)\n        self.assertFalse(expect_log.logged_stack)\n\n# Python's SSL implementation differs significantly between versions.\n# For example, SSLv3 and TLSv1 throw an exception if you try to read\n# from the socket before the handshake is complete, but the default\n# of SSLv23 allows it.\n\n\nclass SSLv23Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_SSLv23\n\n\n@skipIfOldSSL\nclass SSLv3Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_SSLv3\n\n\n@skipIfOldSSL\nclass TLSv1Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_TLSv1\n\n\n@unittest.skipIf(not hasattr(ssl, 'SSLContext'), 'ssl.SSLContext not present')\nclass SSLContextTest(BaseSSLTest, SSLTestMixin):\n    def get_ssl_options(self):\n        context = ssl_options_to_context(\n            AsyncHTTPSTestCase.get_ssl_options(self))\n        assert isinstance(context, ssl.SSLContext)\n        return context\n\n\nclass BadSSLOptionsTest(unittest.TestCase):\n    def test_missing_arguments(self):\n        application = Application()\n        self.assertRaises(KeyError, HTTPServer, application, ssl_options={\n            \"keyfile\": \"/__missing__.crt\",\n        })\n\n    def test_missing_key(self):\n        \"\"\"A missing SSL key should cause an immediate exception.\"\"\"\n\n        application = Application()\n        module_dir = os.path.dirname(__file__)\n        existing_certificate = os.path.join(module_dir, 'test.crt')\n        existing_key = os.path.join(module_dir, 'test.key')\n\n        self.assertRaises((ValueError, IOError),\n                          HTTPServer, application, ssl_options={\n                              \"certfile\": \"/__mising__.crt\",\n        })\n        self.assertRaises((ValueError, IOError),\n                          HTTPServer, application, ssl_options={\n                              \"certfile\": existing_certificate,\n                              \"keyfile\": \"/__missing__.key\"\n        })\n\n        # This actually works because both files exist\n        HTTPServer(application, ssl_options={\n                   \"certfile\": existing_certificate,\n                   \"keyfile\": existing_key,\n                   })\n\n\nclass MultipartTestHandler(RequestHandler):\n    def post(self):\n        self.finish({\"header\": self.request.headers[\"X-Header-Encoding-Test\"],\n                     \"argument\": self.get_argument(\"argument\"),\n                     \"filename\": self.request.files[\"files\"][0].filename,\n                     \"filebody\": _unicode(self.request.files[\"files\"][0][\"body\"]),\n                     })\n\n\n# This test is also called from wsgi_test\nclass HTTPConnectionTest(AsyncHTTPTestCase):\n    def get_handlers(self):\n        return [(\"/multipart\", MultipartTestHandler),\n                (\"/hello\", HelloWorldRequestHandler)]\n\n    def get_app(self):\n        return Application(self.get_handlers())\n\n    def raw_fetch(self, headers, body, newline=b\"\\r\\n\"):\n        with closing(IOStream(socket.socket())) as stream:\n            stream.connect(('127.0.0.1', self.get_http_port()), self.stop)\n            self.wait()\n            stream.write(\n                newline.join(headers +\n                             [utf8(\"Content-Length: %d\" % len(body))]) +\n                newline + newline + body)\n            read_stream_body(stream, self.stop)\n            headers, body = self.wait()\n            return body\n\n    def test_multipart_form(self):\n        # Encodings here are tricky:  Headers are latin1, bodies can be\n        # anything (we use utf8 by default).\n        response = self.raw_fetch([\n            b\"POST /multipart HTTP/1.0\",\n            b\"Content-Type: multipart/form-data; boundary=1234567890\",\n            b\"X-Header-encoding-test: \\xe9\",\n        ],\n            b\"\\r\\n\".join([\n                b\"Content-Disposition: form-data; name=argument\",\n                b\"\",\n                u\"\\u00e1\".encode(\"utf-8\"),\n                b\"--1234567890\",\n                u'Content-Disposition: form-data; name=\"files\"; filename=\"\\u00f3\"'.encode(\"utf8\"),\n                b\"\",\n                u\"\\u00fa\".encode(\"utf-8\"),\n                b\"--1234567890--\",\n                b\"\",\n            ]))\n        data = json_decode(response)\n        self.assertEqual(u\"\\u00e9\", data[\"header\"])\n        self.assertEqual(u\"\\u00e1\", data[\"argument\"])\n        self.assertEqual(u\"\\u00f3\", data[\"filename\"])\n        self.assertEqual(u\"\\u00fa\", data[\"filebody\"])\n\n    def test_newlines(self):\n        # We support both CRLF and bare LF as line separators.\n        for newline in (b\"\\r\\n\", b\"\\n\"):\n            response = self.raw_fetch([b\"GET /hello HTTP/1.0\"], b\"\",\n                                      newline=newline)\n            self.assertEqual(response, b'Hello world')\n\n    def test_100_continue(self):\n        # Run through a 100-continue interaction by hand:\n        # When given Expect: 100-continue, we get a 100 response after the\n        # headers, and then the real response after the body.\n        stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        stream.connect((\"127.0.0.1\", self.get_http_port()), callback=self.stop)\n        self.wait()\n        stream.write(b\"\\r\\n\".join([b\"POST /hello HTTP/1.1\",\n                                   b\"Content-Length: 1024\",\n                                   b\"Expect: 100-continue\",\n                                   b\"Connection: close\",\n                                   b\"\\r\\n\"]), callback=self.stop)\n        self.wait()\n        stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        data = self.wait()\n        self.assertTrue(data.startswith(b\"HTTP/1.1 100 \"), data)\n        stream.write(b\"a\" * 1024)\n        stream.read_until(b\"\\r\\n\", self.stop)\n        first_line = self.wait()\n        self.assertTrue(first_line.startswith(b\"HTTP/1.1 200\"), first_line)\n        stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        header_data = self.wait()\n        headers = HTTPHeaders.parse(native_str(header_data.decode('latin1')))\n        stream.read_bytes(int(headers[\"Content-Length\"]), self.stop)\n        body = self.wait()\n        self.assertEqual(body, b\"Got 1024 bytes in POST\")\n        stream.close()\n\n\nclass EchoHandler(RequestHandler):\n    def get(self):\n        self.write(recursive_unicode(self.request.arguments))\n\n    def post(self):\n        self.write(recursive_unicode(self.request.arguments))\n\n\nclass TypeCheckHandler(RequestHandler):\n    def prepare(self):\n        self.errors = {}\n        fields = [\n            ('method', str),\n            ('uri', str),\n            ('version', str),\n            ('remote_ip', str),\n            ('protocol', str),\n            ('host', str),\n            ('path', str),\n            ('query', str),\n        ]\n        for field, expected_type in fields:\n            self.check_type(field, getattr(self.request, field), expected_type)\n\n        self.check_type('header_key', list(self.request.headers.keys())[0], str)\n        self.check_type('header_value', list(self.request.headers.values())[0], str)\n\n        self.check_type('cookie_key', list(self.request.cookies.keys())[0], str)\n        self.check_type('cookie_value', list(self.request.cookies.values())[0].value, str)\n        # secure cookies\n\n        self.check_type('arg_key', list(self.request.arguments.keys())[0], str)\n        self.check_type('arg_value', list(self.request.arguments.values())[0][0], bytes)\n\n    def post(self):\n        self.check_type('body', self.request.body, bytes)\n        self.write(self.errors)\n\n    def get(self):\n        self.write(self.errors)\n\n    def check_type(self, name, obj, expected_type):\n        actual_type = type(obj)\n        if expected_type != actual_type:\n            self.errors[name] = \"expected %s, got %s\" % (expected_type,\n                                                         actual_type)\n\n\nclass HTTPServerTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([(\"/echo\", EchoHandler),\n                            (\"/typecheck\", TypeCheckHandler),\n                            (\"//doubleslash\", EchoHandler),\n                            ])\n\n    def test_query_string_encoding(self):\n        response = self.fetch(\"/echo?foo=%C3%A9\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u\"foo\": [u\"\\u00e9\"]})\n\n    def test_empty_query_string(self):\n        response = self.fetch(\"/echo?foo=&foo=\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u\"foo\": [u\"\", u\"\"]})\n\n    def test_empty_post_parameters(self):\n        response = self.fetch(\"/echo\", method=\"POST\", body=\"foo=&bar=\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u\"foo\": [u\"\"], u\"bar\": [u\"\"]})\n\n    def test_types(self):\n        headers = {\"Cookie\": \"foo=bar\"}\n        response = self.fetch(\"/typecheck?foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n        response = self.fetch(\"/typecheck\", method=\"POST\", body=\"foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n    def test_double_slash(self):\n        # urlparse.urlsplit (which tornado.httpserver used to use\n        # incorrectly) would parse paths beginning with \"//\" as\n        # protocol-relative urls.\n        response = self.fetch(\"//doubleslash\")\n        self.assertEqual(200, response.code)\n        self.assertEqual(json_decode(response.body), {})\n\n    def test_malformed_body(self):\n        # parse_qs is pretty forgiving, but it will fail on python 3\n        # if the data is not utf8.  On python 2 parse_qs will work,\n        # but then the recursive_unicode call in EchoHandler will\n        # fail.\n        if str is bytes:\n            return\n        with ExpectLog(gen_log, 'Invalid x-www-form-urlencoded body'):\n            response = self.fetch(\n                '/echo', method=\"POST\",\n                headers={'Content-Type': 'application/x-www-form-urlencoded'},\n                body=b'\\xe9')\n        self.assertEqual(200, response.code)\n        self.assertEqual(b'{}', response.body)\n\n\nclass HTTPServerRawTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([\n            ('/echo', EchoHandler),\n        ])\n\n    def setUp(self):\n        super(HTTPServerRawTest, self).setUp()\n        self.stream = IOStream(socket.socket())\n        self.stream.connect(('127.0.0.1', self.get_http_port()), self.stop)\n        self.wait()\n\n    def tearDown(self):\n        self.stream.close()\n        super(HTTPServerRawTest, self).tearDown()\n\n    def test_empty_request(self):\n        self.stream.close()\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()\n\n    def test_malformed_first_line(self):\n        with ExpectLog(gen_log, '.*Malformed HTTP request line'):\n            self.stream.write(b'asdf\\r\\n\\r\\n')\n            # TODO: need an async version of ExpectLog so we don't need\n            # hard-coded timeouts here.\n            self.io_loop.add_timeout(datetime.timedelta(seconds=0.01),\n                                     self.stop)\n            self.wait()\n\n    def test_malformed_headers(self):\n        with ExpectLog(gen_log, '.*Malformed HTTP headers'):\n            self.stream.write(b'GET / HTTP/1.0\\r\\nasdf\\r\\n\\r\\n')\n            self.io_loop.add_timeout(datetime.timedelta(seconds=0.01),\n                                     self.stop)\n            self.wait()\n\n    def test_chunked_request_body(self):\n        # Chunked requests are not widely supported and we don't have a way\n        # to generate them in AsyncHTTPClient, but HTTPServer will read them.\n        self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nTransfer-Encoding: chunked\nContent-Type: application/x-www-form-urlencoded\n\n4\nfoo=\n3\nbar\n0\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n        read_stream_body(self.stream, self.stop)\n        headers, response = self.wait()\n        self.assertEqual(json_decode(response), {u'foo': [u'bar']})\n\n    def test_invalid_content_length(self):\n        with ExpectLog(gen_log, '.*Only integer Content-Length is allowed'):\n            self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nContent-Length: foo\n\nbar\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n            self.stream.read_until_close(self.stop)\n            self.wait()\n\n\nclass XHeaderTest(HandlerBaseTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(dict(remote_ip=self.request.remote_ip,\n                            remote_protocol=self.request.protocol))\n\n    def get_httpserver_options(self):\n        return dict(xheaders=True)\n\n    def test_ip_headers(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_ip\"], \"127.0.0.1\")\n\n        valid_ipv4 = {\"X-Real-IP\": \"4.4.4.4\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv4)[\"remote_ip\"],\n            \"4.4.4.4\")\n\n        valid_ipv4_list = {\"X-Forwarded-For\": \"127.0.0.1, 4.4.4.4\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv4_list)[\"remote_ip\"],\n            \"4.4.4.4\")\n\n        valid_ipv6 = {\"X-Real-IP\": \"2620:0:1cfe:face:b00c::3\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv6)[\"remote_ip\"],\n            \"2620:0:1cfe:face:b00c::3\")\n\n        valid_ipv6_list = {\"X-Forwarded-For\": \"::1, 2620:0:1cfe:face:b00c::3\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv6_list)[\"remote_ip\"],\n            \"2620:0:1cfe:face:b00c::3\")\n\n        invalid_chars = {\"X-Real-IP\": \"4.4.4.4<script>\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=invalid_chars)[\"remote_ip\"],\n            \"127.0.0.1\")\n\n        invalid_chars_list = {\"X-Forwarded-For\": \"4.4.4.4, 5.5.5.5<script>\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=invalid_chars_list)[\"remote_ip\"],\n            \"127.0.0.1\")\n\n        invalid_host = {\"X-Real-IP\": \"www.google.com\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=invalid_host)[\"remote_ip\"],\n            \"127.0.0.1\")\n\n    def test_scheme_headers(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_protocol\"], \"http\")\n\n        https_scheme = {\"X-Scheme\": \"https\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=https_scheme)[\"remote_protocol\"],\n            \"https\")\n\n        https_forwarded = {\"X-Forwarded-Proto\": \"https\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=https_forwarded)[\"remote_protocol\"],\n            \"https\")\n\n        bad_forwarded = {\"X-Forwarded-Proto\": \"unknown\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=bad_forwarded)[\"remote_protocol\"],\n            \"http\")\n\n\nclass SSLXHeaderTest(AsyncHTTPSTestCase, HandlerBaseTestCase):\n    def get_app(self):\n        return Application([('/', XHeaderTest.Handler)])\n\n    def get_httpserver_options(self):\n        output = super(SSLXHeaderTest, self).get_httpserver_options()\n        output['xheaders'] = True\n        return output\n\n    def test_request_without_xprotocol(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_protocol\"], \"https\")\n\n        http_scheme = {\"X-Scheme\": \"http\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=http_scheme)[\"remote_protocol\"], \"http\")\n\n        bad_scheme = {\"X-Scheme\": \"unknown\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=bad_scheme)[\"remote_protocol\"], \"https\")\n\n\nclass ManualProtocolTest(HandlerBaseTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(dict(protocol=self.request.protocol))\n\n    def get_httpserver_options(self):\n        return dict(protocol='https')\n\n    def test_manual_protocol(self):\n        self.assertEqual(self.fetch_json('/')['protocol'], 'https')\n\n\n@unittest.skipIf(not hasattr(socket, 'AF_UNIX') or sys.platform == 'cygwin',\n                 \"unix sockets not supported on this platform\")\nclass UnixSocketTest(AsyncTestCase):\n    \"\"\"HTTPServers can listen on Unix sockets too.\n\n    Why would you want to do this?  Nginx can proxy to backends listening\n    on unix sockets, for one thing (and managing a namespace for unix\n    sockets can be easier than managing a bunch of TCP port numbers).\n\n    Unfortunately, there's no way to specify a unix socket in a url for\n    an HTTP client, so we have to test this by hand.\n    \"\"\"\n    def setUp(self):\n        super(UnixSocketTest, self).setUp()\n        self.tmpdir = tempfile.mkdtemp()\n        self.sockfile = os.path.join(self.tmpdir, \"test.sock\")\n        sock = netutil.bind_unix_socket(self.sockfile)\n        app = Application([(\"/hello\", HelloWorldRequestHandler)])\n        self.server = HTTPServer(app, io_loop=self.io_loop)\n        self.server.add_socket(sock)\n        self.stream = IOStream(socket.socket(socket.AF_UNIX), io_loop=self.io_loop)\n        self.stream.connect(self.sockfile, self.stop)\n        self.wait()\n\n    def tearDown(self):\n        self.stream.close()\n        self.server.stop()\n        shutil.rmtree(self.tmpdir)\n        super(UnixSocketTest, self).tearDown()\n\n    def test_unix_socket(self):\n        self.stream.write(b\"GET /hello HTTP/1.0\\r\\n\\r\\n\")\n        self.stream.read_until(b\"\\r\\n\", self.stop)\n        response = self.wait()\n        self.assertEqual(response, b\"HTTP/1.1 200 OK\\r\\n\")\n        self.stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        headers = HTTPHeaders.parse(self.wait().decode('latin1'))\n        self.stream.read_bytes(int(headers[\"Content-Length\"]), self.stop)\n        body = self.wait()\n        self.assertEqual(body, b\"Hello world\")\n\n    def test_unix_socket_bad_request(self):\n        # Unix sockets don't have remote addresses so they just return an\n        # empty string.\n        with ExpectLog(gen_log, \"Malformed HTTP message from\"):\n            self.stream.write(b\"garbage\\r\\n\\r\\n\")\n            self.stream.read_until_close(self.stop)\n            response = self.wait()\n        self.assertEqual(response, b\"\")\n\n\nclass KeepAliveTest(AsyncHTTPTestCase):\n    \"\"\"Tests various scenarios for HTTP 1.1 keep-alive support.\n\n    These tests don't use AsyncHTTPClient because we want to control\n    connection reuse and closing.\n    \"\"\"\n    def get_app(self):\n        class HelloHandler(RequestHandler):\n            def get(self):\n                self.finish('Hello world')\n\n            def post(self):\n                self.finish('Hello world')\n\n        class LargeHandler(RequestHandler):\n            def get(self):\n                # 512KB should be bigger than the socket buffers so it will\n                # be written out in chunks.\n                self.write(''.join(chr(i % 256) * 1024 for i in range(512)))\n\n        class FinishOnCloseHandler(RequestHandler):\n            @asynchronous\n            def get(self):\n                self.flush()\n\n            def on_connection_close(self):\n                # This is not very realistic, but finishing the request\n                # from the close callback has the right timing to mimic\n                # some errors seen in the wild.\n                self.finish('closed')\n\n        return Application([('/', HelloHandler),\n                            ('/large', LargeHandler),\n                            ('/finish_on_close', FinishOnCloseHandler)])\n\n    def setUp(self):\n        super(KeepAliveTest, self).setUp()\n        self.http_version = b'HTTP/1.1'\n\n    def tearDown(self):\n        # We just closed the client side of the socket; let the IOLoop run\n        # once to make sure the server side got the message.\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()\n\n        if hasattr(self, 'stream'):\n            self.stream.close()\n        super(KeepAliveTest, self).tearDown()\n\n    # The next few methods are a crude manual http client\n    def connect(self):\n        self.stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        self.stream.connect(('127.0.0.1', self.get_http_port()), self.stop)\n        self.wait()\n\n    def read_headers(self):\n        self.stream.read_until(b'\\r\\n', self.stop)\n        first_line = self.wait()\n        self.assertTrue(first_line.startswith(b'HTTP/1.1 200'), first_line)\n        self.stream.read_until(b'\\r\\n\\r\\n', self.stop)\n        header_bytes = self.wait()\n        headers = HTTPHeaders.parse(header_bytes.decode('latin1'))\n        return headers\n\n    def read_response(self):\n        self.headers = self.read_headers()\n        self.stream.read_bytes(int(self.headers['Content-Length']), self.stop)\n        body = self.wait()\n        self.assertEqual(b'Hello world', body)\n\n    def close(self):\n        self.stream.close()\n        del self.stream\n\n    def test_two_requests(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.close()\n\n    def test_request_close(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\nConnection: close\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.read_until_close(callback=self.stop)\n        data = self.wait()\n        self.assertTrue(not data)\n        self.close()\n\n    # keepalive is supported for http 1.0 too, but it's opt-in\n    def test_http10(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.0\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.read_until_close(callback=self.stop)\n        data = self.wait()\n        self.assertTrue(not data)\n        self.assertTrue('Connection' not in self.headers)\n        self.close()\n\n    def test_http10_keepalive(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.close()\n\n    def test_http10_keepalive_extra_crlf(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.close()\n\n    def test_pipelined_requests(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\nGET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.read_response()\n        self.close()\n\n    def test_pipelined_cancel(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\nGET / HTTP/1.1\\r\\n\\r\\n')\n        # only read once\n        self.read_response()\n        self.close()\n\n    def test_cancel_during_download(self):\n        self.connect()\n        self.stream.write(b'GET /large HTTP/1.1\\r\\n\\r\\n')\n        self.read_headers()\n        self.stream.read_bytes(1024, self.stop)\n        self.wait()\n        self.close()\n\n    def test_finish_while_closed(self):\n        self.connect()\n        self.stream.write(b'GET /finish_on_close HTTP/1.1\\r\\n\\r\\n')\n        self.read_headers()\n        self.close()\n\n    def test_keepalive_chunked(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'POST / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n'\n                          b'Transfer-Encoding: chunked\\r\\n'\n                          b'\\r\\n0\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.close()\n\n\nclass GzipBaseTest(object):\n    def get_app(self):\n        return Application([('/', EchoHandler)])\n\n    def post_gzip(self, body):\n        bytesio = BytesIO()\n        gzip_file = gzip.GzipFile(mode='w', fileobj=bytesio)\n        gzip_file.write(utf8(body))\n        gzip_file.close()\n        compressed_body = bytesio.getvalue()\n        return self.fetch('/', method='POST', body=compressed_body,\n                          headers={'Content-Encoding': 'gzip'})\n\n    def test_uncompressed(self):\n        response = self.fetch('/', method='POST', body='foo=bar')\n        self.assertEquals(json_decode(response.body), {u'foo': [u'bar']})\n\n\nclass GzipTest(GzipBaseTest, AsyncHTTPTestCase):\n    def get_httpserver_options(self):\n        return dict(decompress_request=True)\n\n    def test_gzip(self):\n        response = self.post_gzip('foo=bar')\n        self.assertEquals(json_decode(response.body), {u'foo': [u'bar']})\n\n\nclass GzipUnsupportedTest(GzipBaseTest, AsyncHTTPTestCase):\n    def test_gzip_unsupported(self):\n        # Gzip support is opt-in; without it the server fails to parse\n        # the body (but parsing form bodies is currently just a log message,\n        # not a fatal error).\n        with ExpectLog(gen_log, \"Unsupported Content-Encoding\"):\n            response = self.post_gzip('foo=bar')\n        self.assertEquals(json_decode(response.body), {})\n\n\nclass StreamingChunkSizeTest(AsyncHTTPTestCase):\n    # 50 characters long, and repetitive so it can be compressed.\n    BODY = b'01234567890123456789012345678901234567890123456789'\n    CHUNK_SIZE = 16\n\n    def get_http_client(self):\n        # body_producer doesn't work on curl_httpclient, so override the\n        # configured AsyncHTTPClient implementation.\n        return SimpleAsyncHTTPClient(io_loop=self.io_loop)\n\n    def get_httpserver_options(self):\n        return dict(chunk_size=self.CHUNK_SIZE, decompress_request=True)\n\n    class MessageDelegate(HTTPMessageDelegate):\n        def __init__(self, connection):\n            self.connection = connection\n\n        def headers_received(self, start_line, headers):\n            self.chunk_lengths = []\n\n        def data_received(self, chunk):\n            self.chunk_lengths.append(len(chunk))\n\n        def finish(self):\n            response_body = utf8(json_encode(self.chunk_lengths))\n            self.connection.write_headers(\n                ResponseStartLine('HTTP/1.1', 200, 'OK'),\n                HTTPHeaders({'Content-Length': str(len(response_body))}))\n            self.connection.write(response_body)\n            self.connection.finish()\n\n    def get_app(self):\n        class App(HTTPServerConnectionDelegate):\n            def start_request(self, server_conn, request_conn):\n                return StreamingChunkSizeTest.MessageDelegate(request_conn)\n        return App()\n\n    def fetch_chunk_sizes(self, **kwargs):\n        response = self.fetch('/', method='POST', **kwargs)\n        response.rethrow()\n        chunks = json_decode(response.body)\n        self.assertEqual(len(self.BODY), sum(chunks))\n        for chunk_size in chunks:\n            self.assertLessEqual(chunk_size, self.CHUNK_SIZE,\n                                 'oversized chunk: ' + str(chunks))\n            self.assertGreater(chunk_size, 0,\n                               'empty chunk: ' + str(chunks))\n        return chunks\n\n    def compress(self, body):\n        bytesio = BytesIO()\n        gzfile = gzip.GzipFile(mode='w', fileobj=bytesio)\n        gzfile.write(body)\n        gzfile.close()\n        compressed = bytesio.getvalue()\n        if len(compressed) >= len(body):\n            raise Exception(\"body did not shrink when compressed\")\n        return compressed\n\n    def test_regular_body(self):\n        chunks = self.fetch_chunk_sizes(body=self.BODY)\n        # Without compression we know exactly what to expect.\n        self.assertEqual([16, 16, 16, 2], chunks)\n\n    def test_compressed_body(self):\n        self.fetch_chunk_sizes(body=self.compress(self.BODY),\n                               headers={'Content-Encoding': 'gzip'})\n        # Compression creates irregular boundaries so the assertions\n        # in fetch_chunk_sizes are as specific as we can get.\n\n    def test_chunked_body(self):\n        def body_producer(write):\n            write(self.BODY[:20])\n            write(self.BODY[20:])\n        chunks = self.fetch_chunk_sizes(body_producer=body_producer)\n        # HTTP chunk boundaries translate to application-visible breaks\n        self.assertEqual([16, 4, 16, 14], chunks)\n\n    def test_chunked_compressed(self):\n        compressed = self.compress(self.BODY)\n        self.assertGreater(len(compressed), 20)\n\n        def body_producer(write):\n            write(compressed[:20])\n            write(compressed[20:])\n        self.fetch_chunk_sizes(body_producer=body_producer,\n                               headers={'Content-Encoding': 'gzip'})\n\n\nclass MaxHeaderSizeTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([('/', HelloWorldRequestHandler)])\n\n    def get_httpserver_options(self):\n        return dict(max_header_size=1024)\n\n    def test_small_headers(self):\n        response = self.fetch(\"/\", headers={'X-Filler': 'a' * 100})\n        response.rethrow()\n        self.assertEqual(response.body, b\"Hello world\")\n\n    def test_large_headers(self):\n        with ExpectLog(gen_log, \"Unsatisfiable read\", required=False):\n            response = self.fetch(\"/\", headers={'X-Filler': 'a' * 1000})\n        # 431 is \"Request Header Fields Too Large\", defined in RFC\n        # 6585. However, many implementations just close the\n        # connection in this case, resulting in a 599.\n        self.assertIn(response.code, (431, 599))\n\n\n@skipOnTravis\nclass IdleTimeoutTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([('/', HelloWorldRequestHandler)])\n\n    def get_httpserver_options(self):\n        return dict(idle_connection_timeout=0.1)\n\n    def setUp(self):\n        super(IdleTimeoutTest, self).setUp()\n        self.streams = []\n\n    def tearDown(self):\n        super(IdleTimeoutTest, self).tearDown()\n        for stream in self.streams:\n            stream.close()\n\n    def connect(self):\n        stream = IOStream(socket.socket())\n        stream.connect(('127.0.0.1', self.get_http_port()), self.stop)\n        self.wait()\n        self.streams.append(stream)\n        return stream\n\n    def test_unused_connection(self):\n        stream = self.connect()\n        stream.set_close_callback(self.stop)\n        self.wait()\n\n    def test_idle_after_use(self):\n        stream = self.connect()\n        stream.set_close_callback(lambda: self.stop(\"closed\"))\n\n        # Use the connection twice to make sure keep-alives are working\n        for i in range(2):\n            stream.write(b\"GET / HTTP/1.1\\r\\n\\r\\n\")\n            stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n            self.wait()\n            stream.read_bytes(11, self.stop)\n            data = self.wait()\n            self.assertEqual(data, b\"Hello world\")\n\n        # Now let the timeout trigger and close the connection.\n        data = self.wait()\n        self.assertEqual(data, \"closed\")\n\n\nclass BodyLimitsTest(AsyncHTTPTestCase):\n    def get_app(self):\n        class BufferedHandler(RequestHandler):\n            def put(self):\n                self.write(str(len(self.request.body)))\n\n        @stream_request_body\n        class StreamingHandler(RequestHandler):\n            def initialize(self):\n                self.bytes_read = 0\n\n            def prepare(self):\n                if 'expected_size' in self.request.arguments:\n                    self.request.connection.set_max_body_size(\n                        int(self.get_argument('expected_size')))\n                if 'body_timeout' in self.request.arguments:\n                    self.request.connection.set_body_timeout(\n                        float(self.get_argument('body_timeout')))\n\n            def data_received(self, data):\n                self.bytes_read += len(data)\n\n            def put(self):\n                self.write(str(self.bytes_read))\n\n        return Application([('/buffered', BufferedHandler),\n                            ('/streaming', StreamingHandler)])\n\n    def get_httpserver_options(self):\n        return dict(body_timeout=3600, max_body_size=4096)\n\n    def get_http_client(self):\n        # body_producer doesn't work on curl_httpclient, so override the\n        # configured AsyncHTTPClient implementation.\n        return SimpleAsyncHTTPClient(io_loop=self.io_loop)\n\n    def test_small_body(self):\n        response = self.fetch('/buffered', method='PUT', body=b'a' * 4096)\n        self.assertEqual(response.body, b'4096')\n        response = self.fetch('/streaming', method='PUT', body=b'a' * 4096)\n        self.assertEqual(response.body, b'4096')\n\n    def test_large_body_buffered(self):\n        with ExpectLog(gen_log, '.*Content-Length too long'):\n            response = self.fetch('/buffered', method='PUT', body=b'a' * 10240)\n        self.assertEqual(response.code, 599)\n\n    def test_large_body_buffered_chunked(self):\n        with ExpectLog(gen_log, '.*chunked body too large'):\n            response = self.fetch('/buffered', method='PUT',\n                                  body_producer=lambda write: write(b'a' * 10240))\n        self.assertEqual(response.code, 599)\n\n    def test_large_body_streaming(self):\n        with ExpectLog(gen_log, '.*Content-Length too long'):\n            response = self.fetch('/streaming', method='PUT', body=b'a' * 10240)\n        self.assertEqual(response.code, 599)\n\n    def test_large_body_streaming_chunked(self):\n        with ExpectLog(gen_log, '.*chunked body too large'):\n            response = self.fetch('/streaming', method='PUT',\n                                  body_producer=lambda write: write(b'a' * 10240))\n        self.assertEqual(response.code, 599)\n\n    def test_large_body_streaming_override(self):\n        response = self.fetch('/streaming?expected_size=10240', method='PUT',\n                              body=b'a' * 10240)\n        self.assertEqual(response.body, b'10240')\n\n    def test_large_body_streaming_chunked_override(self):\n        response = self.fetch('/streaming?expected_size=10240', method='PUT',\n                              body_producer=lambda write: write(b'a' * 10240))\n        self.assertEqual(response.body, b'10240')\n\n    @gen_test\n    def test_timeout(self):\n        stream = IOStream(socket.socket())\n        try:\n            yield stream.connect(('127.0.0.1', self.get_http_port()))\n            # Use a raw stream because AsyncHTTPClient won't let us read a\n            # response without finishing a body.\n            stream.write(b'PUT /streaming?body_timeout=0.1 HTTP/1.0\\r\\n'\n                         b'Content-Length: 42\\r\\n\\r\\n')\n            with ExpectLog(gen_log, 'Timeout reading body'):\n                response = yield stream.read_until_close()\n            self.assertEqual(response, b'')\n        finally:\n            stream.close()\n\n    @gen_test\n    def test_body_size_override_reset(self):\n        # The max_body_size override is reset between requests.\n        stream = IOStream(socket.socket())\n        try:\n            yield stream.connect(('127.0.0.1', self.get_http_port()))\n            # Use a raw stream so we can make sure it's all on one connection.\n            stream.write(b'PUT /streaming?expected_size=10240 HTTP/1.1\\r\\n'\n                         b'Content-Length: 10240\\r\\n\\r\\n')\n            stream.write(b'a' * 10240)\n            headers, response = yield gen.Task(read_stream_body, stream)\n            self.assertEqual(response, b'10240')\n            # Without the ?expected_size parameter, we get the old default value\n            stream.write(b'PUT /streaming HTTP/1.1\\r\\n'\n                         b'Content-Length: 10240\\r\\n\\r\\n')\n            with ExpectLog(gen_log, '.*Content-Length too long'):\n                data = yield stream.read_until_close()\n            self.assertEqual(data, b'')\n        finally:\n            stream.close()\n\n\nclass LegacyInterfaceTest(AsyncHTTPTestCase):\n    def get_app(self):\n        # The old request_callback interface does not implement the\n        # delegate interface, and writes its response via request.write\n        # instead of request.connection.write_headers.\n        def handle_request(request):\n            self.http1 = request.version.startswith(\"HTTP/1.\")\n            if not self.http1:\n                # This test will be skipped if we're using HTTP/2,\n                # so just close it out cleanly using the modern interface.\n                request.connection.write_headers(\n                    ResponseStartLine('', 200, 'OK'),\n                    HTTPHeaders())\n                request.connection.finish()\n                return\n            message = b\"Hello world\"\n            request.write(utf8(\"HTTP/1.1 200 OK\\r\\n\"\n                               \"Content-Length: %d\\r\\n\\r\\n\" % len(message)))\n            request.write(message)\n            request.finish()\n        return handle_request\n\n    def test_legacy_interface(self):\n        response = self.fetch('/')\n        if not self.http1:\n            self.skipTest(\"requires HTTP/1.x\")\n        self.assertEqual(response.body, b\"Hello world\")\n",
            "new_file_content": "#!/usr/bin/env python\n\n\nfrom __future__ import absolute_import, division, print_function, with_statement\nfrom tornado import netutil\nfrom tornado.escape import json_decode, json_encode, utf8, _unicode, recursive_unicode, native_str\nfrom tornado import gen\nfrom tornado.http1connection import HTTP1Connection\nfrom tornado.httpserver import HTTPServer\nfrom tornado.httputil import HTTPHeaders, HTTPMessageDelegate, HTTPServerConnectionDelegate, ResponseStartLine\nfrom tornado.iostream import IOStream\nfrom tornado.log import gen_log\nfrom tornado.netutil import ssl_options_to_context\nfrom tornado.simple_httpclient import SimpleAsyncHTTPClient\nfrom tornado.testing import AsyncHTTPTestCase, AsyncHTTPSTestCase, AsyncTestCase, ExpectLog, gen_test\nfrom tornado.test.util import unittest, skipOnTravis\nfrom tornado.web import Application, RequestHandler, asynchronous, stream_request_body\nfrom contextlib import closing\nimport datetime\nimport gzip\nimport os\nimport shutil\nimport socket\nimport ssl\nimport sys\nimport tempfile\nfrom io import BytesIO\n\n\ndef read_stream_body(stream, callback):\n    \"\"\"Reads an HTTP response from `stream` and runs callback with its\n    headers and body.\"\"\"\n    chunks = []\n\n    class Delegate(HTTPMessageDelegate):\n        def headers_received(self, start_line, headers):\n            self.headers = headers\n\n        def data_received(self, chunk):\n            chunks.append(chunk)\n\n        def finish(self):\n            callback((self.headers, b''.join(chunks)))\n    conn = HTTP1Connection(stream, True)\n    conn.read_response(Delegate())\n\n\nclass HandlerBaseTestCase(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([('/', self.__class__.Handler)])\n\n    def fetch_json(self, *args, **kwargs):\n        response = self.fetch(*args, **kwargs)\n        response.rethrow()\n        return json_decode(response.body)\n\n\nclass HelloWorldRequestHandler(RequestHandler):\n    def initialize(self, protocol=\"http\"):\n        self.expected_protocol = protocol\n\n    def get(self):\n        if self.request.protocol != self.expected_protocol:\n            raise Exception(\"unexpected protocol\")\n        self.finish(\"Hello world\")\n\n    def post(self):\n        self.finish(\"Got %d bytes in POST\" % len(self.request.body))\n\n\n# In pre-1.0 versions of openssl, SSLv23 clients always send SSLv2\n# ClientHello messages, which are rejected by SSLv3 and TLSv1\n# servers.  Note that while the OPENSSL_VERSION_INFO was formally\n# introduced in python3.2, it was present but undocumented in\n# python 2.7\nskipIfOldSSL = unittest.skipIf(\n    getattr(ssl, 'OPENSSL_VERSION_INFO', (0, 0)) < (1, 0),\n    \"old version of ssl module and/or openssl\")\n\n\nclass BaseSSLTest(AsyncHTTPSTestCase):\n    def get_app(self):\n        return Application([('/', HelloWorldRequestHandler,\n                             dict(protocol=\"https\"))])\n\n\nclass SSLTestMixin(object):\n    def get_ssl_options(self):\n        return dict(ssl_version=self.get_ssl_version(),  # type: ignore\n                    **AsyncHTTPSTestCase.get_ssl_options())\n\n    def get_ssl_version(self):\n        raise NotImplementedError()\n\n    def test_ssl(self):\n        response = self.fetch('/')\n        self.assertEqual(response.body, b\"Hello world\")\n\n    def test_large_post(self):\n        response = self.fetch('/',\n                              method='POST',\n                              body='A' * 5000)\n        self.assertEqual(response.body, b\"Got 5000 bytes in POST\")\n\n    def test_non_ssl_request(self):\n        # Make sure the server closes the connection when it gets a non-ssl\n        # connection, rather than waiting for a timeout or otherwise\n        # misbehaving.\n        with ExpectLog(gen_log, '(SSL Error|uncaught exception)'):\n            with ExpectLog(gen_log, 'Uncaught exception', required=False):\n                self.http_client.fetch(\n                    self.get_url(\"/\").replace('https:', 'http:'),\n                    self.stop,\n                    request_timeout=3600,\n                    connect_timeout=3600)\n                response = self.wait()\n        self.assertEqual(response.code, 599)\n\n    def test_error_logging(self):\n        # No stack traces are logged for SSL errors.\n        with ExpectLog(gen_log, 'SSL Error') as expect_log:\n            self.http_client.fetch(\n                self.get_url(\"/\").replace(\"https:\", \"http:\"),\n                self.stop)\n            response = self.wait()\n            self.assertEqual(response.code, 599)\n        self.assertFalse(expect_log.logged_stack)\n\n# Python's SSL implementation differs significantly between versions.\n# For example, SSLv3 and TLSv1 throw an exception if you try to read\n# from the socket before the handshake is complete, but the default\n# of SSLv23 allows it.\n\n\nclass SSLv23Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_SSLv23\n\n\n@skipIfOldSSL\nclass SSLv3Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_SSLv3\n\n\n@skipIfOldSSL\nclass TLSv1Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_TLSv1\n\n\n@unittest.skipIf(not hasattr(ssl, 'SSLContext'), 'ssl.SSLContext not present')\nclass SSLContextTest(BaseSSLTest, SSLTestMixin):\n    def get_ssl_options(self):\n        context = ssl_options_to_context(\n            AsyncHTTPSTestCase.get_ssl_options(self))\n        assert isinstance(context, ssl.SSLContext)\n        return context\n\n\nclass BadSSLOptionsTest(unittest.TestCase):\n    def test_missing_arguments(self):\n        application = Application()\n        self.assertRaises(KeyError, HTTPServer, application, ssl_options={\n            \"keyfile\": \"/__missing__.crt\",\n        })\n\n    def test_missing_key(self):\n        \"\"\"A missing SSL key should cause an immediate exception.\"\"\"\n\n        application = Application()\n        module_dir = os.path.dirname(__file__)\n        existing_certificate = os.path.join(module_dir, 'test.crt')\n        existing_key = os.path.join(module_dir, 'test.key')\n\n        self.assertRaises((ValueError, IOError),\n                          HTTPServer, application, ssl_options={\n                              \"certfile\": \"/__mising__.crt\",\n        })\n        self.assertRaises((ValueError, IOError),\n                          HTTPServer, application, ssl_options={\n                              \"certfile\": existing_certificate,\n                              \"keyfile\": \"/__missing__.key\"\n        })\n\n        # This actually works because both files exist\n        HTTPServer(application, ssl_options={\n                   \"certfile\": existing_certificate,\n                   \"keyfile\": existing_key,\n                   })\n\n\nclass MultipartTestHandler(RequestHandler):\n    def post(self):\n        self.finish({\"header\": self.request.headers[\"X-Header-Encoding-Test\"],\n                     \"argument\": self.get_argument(\"argument\"),\n                     \"filename\": self.request.files[\"files\"][0].filename,\n                     \"filebody\": _unicode(self.request.files[\"files\"][0][\"body\"]),\n                     })\n\n\n# This test is also called from wsgi_test\nclass HTTPConnectionTest(AsyncHTTPTestCase):\n    def get_handlers(self):\n        return [(\"/multipart\", MultipartTestHandler),\n                (\"/hello\", HelloWorldRequestHandler)]\n\n    def get_app(self):\n        return Application(self.get_handlers())\n\n    def raw_fetch(self, headers, body, newline=b\"\\r\\n\"):\n        with closing(IOStream(socket.socket())) as stream:\n            stream.connect(('127.0.0.1', self.get_http_port()), self.stop)\n            self.wait()\n            stream.write(\n                newline.join(headers +\n                             [utf8(\"Content-Length: %d\" % len(body))]) +\n                newline + newline + body)\n            read_stream_body(stream, self.stop)\n            headers, body = self.wait()\n            return body\n\n    def test_multipart_form(self):\n        # Encodings here are tricky:  Headers are latin1, bodies can be\n        # anything (we use utf8 by default).\n        response = self.raw_fetch([\n            b\"POST /multipart HTTP/1.0\",\n            b\"Content-Type: multipart/form-data; boundary=1234567890\",\n            b\"X-Header-encoding-test: \\xe9\",\n        ],\n            b\"\\r\\n\".join([\n                b\"Content-Disposition: form-data; name=argument\",\n                b\"\",\n                u\"\\u00e1\".encode(\"utf-8\"),\n                b\"--1234567890\",\n                u'Content-Disposition: form-data; name=\"files\"; filename=\"\\u00f3\"'.encode(\"utf8\"),\n                b\"\",\n                u\"\\u00fa\".encode(\"utf-8\"),\n                b\"--1234567890--\",\n                b\"\",\n            ]))\n        data = json_decode(response)\n        self.assertEqual(u\"\\u00e9\", data[\"header\"])\n        self.assertEqual(u\"\\u00e1\", data[\"argument\"])\n        self.assertEqual(u\"\\u00f3\", data[\"filename\"])\n        self.assertEqual(u\"\\u00fa\", data[\"filebody\"])\n\n    def test_newlines(self):\n        # We support both CRLF and bare LF as line separators.\n        for newline in (b\"\\r\\n\", b\"\\n\"):\n            response = self.raw_fetch([b\"GET /hello HTTP/1.0\"], b\"\",\n                                      newline=newline)\n            self.assertEqual(response, b'Hello world')\n\n    def test_100_continue(self):\n        # Run through a 100-continue interaction by hand:\n        # When given Expect: 100-continue, we get a 100 response after the\n        # headers, and then the real response after the body.\n        stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        stream.connect((\"127.0.0.1\", self.get_http_port()), callback=self.stop)\n        self.wait()\n        stream.write(b\"\\r\\n\".join([b\"POST /hello HTTP/1.1\",\n                                   b\"Content-Length: 1024\",\n                                   b\"Expect: 100-continue\",\n                                   b\"Connection: close\",\n                                   b\"\\r\\n\"]), callback=self.stop)\n        self.wait()\n        stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        data = self.wait()\n        self.assertTrue(data.startswith(b\"HTTP/1.1 100 \"), data)\n        stream.write(b\"a\" * 1024)\n        stream.read_until(b\"\\r\\n\", self.stop)\n        first_line = self.wait()\n        self.assertTrue(first_line.startswith(b\"HTTP/1.1 200\"), first_line)\n        stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        header_data = self.wait()\n        headers = HTTPHeaders.parse(native_str(header_data.decode('latin1')))\n        stream.read_bytes(int(headers[\"Content-Length\"]), self.stop)\n        body = self.wait()\n        self.assertEqual(body, b\"Got 1024 bytes in POST\")\n        stream.close()\n\n\nclass EchoHandler(RequestHandler):\n    def get(self):\n        self.write(recursive_unicode(self.request.arguments))\n\n    def post(self):\n        self.write(recursive_unicode(self.request.arguments))\n\n\nclass TypeCheckHandler(RequestHandler):\n    def prepare(self):\n        self.errors = {}\n        fields = [\n            ('method', str),\n            ('uri', str),\n            ('version', str),\n            ('remote_ip', str),\n            ('protocol', str),\n            ('host', str),\n            ('path', str),\n            ('query', str),\n        ]\n        for field, expected_type in fields:\n            self.check_type(field, getattr(self.request, field), expected_type)\n\n        self.check_type('header_key', list(self.request.headers.keys())[0], str)\n        self.check_type('header_value', list(self.request.headers.values())[0], str)\n\n        self.check_type('cookie_key', list(self.request.cookies.keys())[0], str)\n        self.check_type('cookie_value', list(self.request.cookies.values())[0].value, str)\n        # secure cookies\n\n        self.check_type('arg_key', list(self.request.arguments.keys())[0], str)\n        self.check_type('arg_value', list(self.request.arguments.values())[0][0], bytes)\n\n    def post(self):\n        self.check_type('body', self.request.body, bytes)\n        self.write(self.errors)\n\n    def get(self):\n        self.write(self.errors)\n\n    def check_type(self, name, obj, expected_type):\n        actual_type = type(obj)\n        if expected_type != actual_type:\n            self.errors[name] = \"expected %s, got %s\" % (expected_type,\n                                                         actual_type)\n\n\nclass HTTPServerTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([(\"/echo\", EchoHandler),\n                            (\"/typecheck\", TypeCheckHandler),\n                            (\"//doubleslash\", EchoHandler),\n                            ])\n\n    def test_query_string_encoding(self):\n        response = self.fetch(\"/echo?foo=%C3%A9\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u\"foo\": [u\"\\u00e9\"]})\n\n    def test_empty_query_string(self):\n        response = self.fetch(\"/echo?foo=&foo=\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u\"foo\": [u\"\", u\"\"]})\n\n    def test_empty_post_parameters(self):\n        response = self.fetch(\"/echo\", method=\"POST\", body=\"foo=&bar=\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u\"foo\": [u\"\"], u\"bar\": [u\"\"]})\n\n    def test_types(self):\n        headers = {\"Cookie\": \"foo=bar\"}\n        response = self.fetch(\"/typecheck?foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n        response = self.fetch(\"/typecheck\", method=\"POST\", body=\"foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n    def test_double_slash(self):\n        # urlparse.urlsplit (which tornado.httpserver used to use\n        # incorrectly) would parse paths beginning with \"//\" as\n        # protocol-relative urls.\n        response = self.fetch(\"//doubleslash\")\n        self.assertEqual(200, response.code)\n        self.assertEqual(json_decode(response.body), {})\n\n    def test_malformed_body(self):\n        # parse_qs is pretty forgiving, but it will fail on python 3\n        # if the data is not utf8.  On python 2 parse_qs will work,\n        # but then the recursive_unicode call in EchoHandler will\n        # fail.\n        if str is bytes:\n            return\n        with ExpectLog(gen_log, 'Invalid x-www-form-urlencoded body'):\n            response = self.fetch(\n                '/echo', method=\"POST\",\n                headers={'Content-Type': 'application/x-www-form-urlencoded'},\n                body=b'\\xe9')\n        self.assertEqual(200, response.code)\n        self.assertEqual(b'{}', response.body)\n\n\nclass HTTPServerRawTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([\n            ('/echo', EchoHandler),\n        ])\n\n    def setUp(self):\n        super(HTTPServerRawTest, self).setUp()\n        self.stream = IOStream(socket.socket())\n        self.stream.connect(('127.0.0.1', self.get_http_port()), self.stop)\n        self.wait()\n\n    def tearDown(self):\n        self.stream.close()\n        super(HTTPServerRawTest, self).tearDown()\n\n    def test_empty_request(self):\n        self.stream.close()\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()\n\n    def test_malformed_first_line(self):\n        with ExpectLog(gen_log, '.*Malformed HTTP request line'):\n            self.stream.write(b'asdf\\r\\n\\r\\n')\n            # TODO: need an async version of ExpectLog so we don't need\n            # hard-coded timeouts here.\n            self.io_loop.add_timeout(datetime.timedelta(seconds=0.01),\n                                     self.stop)\n            self.wait()\n\n    def test_malformed_headers(self):\n        with ExpectLog(gen_log, '.*Malformed HTTP headers'):\n            self.stream.write(b'GET / HTTP/1.0\\r\\nasdf\\r\\n\\r\\n')\n            self.io_loop.add_timeout(datetime.timedelta(seconds=0.01),\n                                     self.stop)\n            self.wait()\n\n    def test_chunked_request_body(self):\n        # Chunked requests are not widely supported and we don't have a way\n        # to generate them in AsyncHTTPClient, but HTTPServer will read them.\n        self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nTransfer-Encoding: chunked\nContent-Type: application/x-www-form-urlencoded\n\n4\nfoo=\n3\nbar\n0\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n        read_stream_body(self.stream, self.stop)\n        headers, response = self.wait()\n        self.assertEqual(json_decode(response), {u'foo': [u'bar']})\n\n    def test_chunked_request_uppercase(self):\n        # As per RFC 2616 section 3.6, \"Transfer-Encoding\" header's value is\n        # case-insensitive.\n        self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nTransfer-Encoding: Chunked\nContent-Type: application/x-www-form-urlencoded\n\n4\nfoo=\n3\nbar\n0\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n        read_stream_body(self.stream, self.stop)\n        headers, response = self.wait()\n        self.assertEqual(json_decode(response), {u'foo': [u'bar']})\n\n    def test_invalid_content_length(self):\n        with ExpectLog(gen_log, '.*Only integer Content-Length is allowed'):\n            self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nContent-Length: foo\n\nbar\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n            self.stream.read_until_close(self.stop)\n            self.wait()\n\n\nclass XHeaderTest(HandlerBaseTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(dict(remote_ip=self.request.remote_ip,\n                            remote_protocol=self.request.protocol))\n\n    def get_httpserver_options(self):\n        return dict(xheaders=True)\n\n    def test_ip_headers(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_ip\"], \"127.0.0.1\")\n\n        valid_ipv4 = {\"X-Real-IP\": \"4.4.4.4\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv4)[\"remote_ip\"],\n            \"4.4.4.4\")\n\n        valid_ipv4_list = {\"X-Forwarded-For\": \"127.0.0.1, 4.4.4.4\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv4_list)[\"remote_ip\"],\n            \"4.4.4.4\")\n\n        valid_ipv6 = {\"X-Real-IP\": \"2620:0:1cfe:face:b00c::3\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv6)[\"remote_ip\"],\n            \"2620:0:1cfe:face:b00c::3\")\n\n        valid_ipv6_list = {\"X-Forwarded-For\": \"::1, 2620:0:1cfe:face:b00c::3\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv6_list)[\"remote_ip\"],\n            \"2620:0:1cfe:face:b00c::3\")\n\n        invalid_chars = {\"X-Real-IP\": \"4.4.4.4<script>\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=invalid_chars)[\"remote_ip\"],\n            \"127.0.0.1\")\n\n        invalid_chars_list = {\"X-Forwarded-For\": \"4.4.4.4, 5.5.5.5<script>\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=invalid_chars_list)[\"remote_ip\"],\n            \"127.0.0.1\")\n\n        invalid_host = {\"X-Real-IP\": \"www.google.com\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=invalid_host)[\"remote_ip\"],\n            \"127.0.0.1\")\n\n    def test_scheme_headers(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_protocol\"], \"http\")\n\n        https_scheme = {\"X-Scheme\": \"https\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=https_scheme)[\"remote_protocol\"],\n            \"https\")\n\n        https_forwarded = {\"X-Forwarded-Proto\": \"https\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=https_forwarded)[\"remote_protocol\"],\n            \"https\")\n\n        bad_forwarded = {\"X-Forwarded-Proto\": \"unknown\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=bad_forwarded)[\"remote_protocol\"],\n            \"http\")\n\n\nclass SSLXHeaderTest(AsyncHTTPSTestCase, HandlerBaseTestCase):\n    def get_app(self):\n        return Application([('/', XHeaderTest.Handler)])\n\n    def get_httpserver_options(self):\n        output = super(SSLXHeaderTest, self).get_httpserver_options()\n        output['xheaders'] = True\n        return output\n\n    def test_request_without_xprotocol(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_protocol\"], \"https\")\n\n        http_scheme = {\"X-Scheme\": \"http\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=http_scheme)[\"remote_protocol\"], \"http\")\n\n        bad_scheme = {\"X-Scheme\": \"unknown\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=bad_scheme)[\"remote_protocol\"], \"https\")\n\n\nclass ManualProtocolTest(HandlerBaseTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(dict(protocol=self.request.protocol))\n\n    def get_httpserver_options(self):\n        return dict(protocol='https')\n\n    def test_manual_protocol(self):\n        self.assertEqual(self.fetch_json('/')['protocol'], 'https')\n\n\n@unittest.skipIf(not hasattr(socket, 'AF_UNIX') or sys.platform == 'cygwin',\n                 \"unix sockets not supported on this platform\")\nclass UnixSocketTest(AsyncTestCase):\n    \"\"\"HTTPServers can listen on Unix sockets too.\n\n    Why would you want to do this?  Nginx can proxy to backends listening\n    on unix sockets, for one thing (and managing a namespace for unix\n    sockets can be easier than managing a bunch of TCP port numbers).\n\n    Unfortunately, there's no way to specify a unix socket in a url for\n    an HTTP client, so we have to test this by hand.\n    \"\"\"\n    def setUp(self):\n        super(UnixSocketTest, self).setUp()\n        self.tmpdir = tempfile.mkdtemp()\n        self.sockfile = os.path.join(self.tmpdir, \"test.sock\")\n        sock = netutil.bind_unix_socket(self.sockfile)\n        app = Application([(\"/hello\", HelloWorldRequestHandler)])\n        self.server = HTTPServer(app, io_loop=self.io_loop)\n        self.server.add_socket(sock)\n        self.stream = IOStream(socket.socket(socket.AF_UNIX), io_loop=self.io_loop)\n        self.stream.connect(self.sockfile, self.stop)\n        self.wait()\n\n    def tearDown(self):\n        self.stream.close()\n        self.server.stop()\n        shutil.rmtree(self.tmpdir)\n        super(UnixSocketTest, self).tearDown()\n\n    def test_unix_socket(self):\n        self.stream.write(b\"GET /hello HTTP/1.0\\r\\n\\r\\n\")\n        self.stream.read_until(b\"\\r\\n\", self.stop)\n        response = self.wait()\n        self.assertEqual(response, b\"HTTP/1.1 200 OK\\r\\n\")\n        self.stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        headers = HTTPHeaders.parse(self.wait().decode('latin1'))\n        self.stream.read_bytes(int(headers[\"Content-Length\"]), self.stop)\n        body = self.wait()\n        self.assertEqual(body, b\"Hello world\")\n\n    def test_unix_socket_bad_request(self):\n        # Unix sockets don't have remote addresses so they just return an\n        # empty string.\n        with ExpectLog(gen_log, \"Malformed HTTP message from\"):\n            self.stream.write(b\"garbage\\r\\n\\r\\n\")\n            self.stream.read_until_close(self.stop)\n            response = self.wait()\n        self.assertEqual(response, b\"\")\n\n\nclass KeepAliveTest(AsyncHTTPTestCase):\n    \"\"\"Tests various scenarios for HTTP 1.1 keep-alive support.\n\n    These tests don't use AsyncHTTPClient because we want to control\n    connection reuse and closing.\n    \"\"\"\n    def get_app(self):\n        class HelloHandler(RequestHandler):\n            def get(self):\n                self.finish('Hello world')\n\n            def post(self):\n                self.finish('Hello world')\n\n        class LargeHandler(RequestHandler):\n            def get(self):\n                # 512KB should be bigger than the socket buffers so it will\n                # be written out in chunks.\n                self.write(''.join(chr(i % 256) * 1024 for i in range(512)))\n\n        class FinishOnCloseHandler(RequestHandler):\n            @asynchronous\n            def get(self):\n                self.flush()\n\n            def on_connection_close(self):\n                # This is not very realistic, but finishing the request\n                # from the close callback has the right timing to mimic\n                # some errors seen in the wild.\n                self.finish('closed')\n\n        return Application([('/', HelloHandler),\n                            ('/large', LargeHandler),\n                            ('/finish_on_close', FinishOnCloseHandler)])\n\n    def setUp(self):\n        super(KeepAliveTest, self).setUp()\n        self.http_version = b'HTTP/1.1'\n\n    def tearDown(self):\n        # We just closed the client side of the socket; let the IOLoop run\n        # once to make sure the server side got the message.\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()\n\n        if hasattr(self, 'stream'):\n            self.stream.close()\n        super(KeepAliveTest, self).tearDown()\n\n    # The next few methods are a crude manual http client\n    def connect(self):\n        self.stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        self.stream.connect(('127.0.0.1', self.get_http_port()), self.stop)\n        self.wait()\n\n    def read_headers(self):\n        self.stream.read_until(b'\\r\\n', self.stop)\n        first_line = self.wait()\n        self.assertTrue(first_line.startswith(b'HTTP/1.1 200'), first_line)\n        self.stream.read_until(b'\\r\\n\\r\\n', self.stop)\n        header_bytes = self.wait()\n        headers = HTTPHeaders.parse(header_bytes.decode('latin1'))\n        return headers\n\n    def read_response(self):\n        self.headers = self.read_headers()\n        self.stream.read_bytes(int(self.headers['Content-Length']), self.stop)\n        body = self.wait()\n        self.assertEqual(b'Hello world', body)\n\n    def close(self):\n        self.stream.close()\n        del self.stream\n\n    def test_two_requests(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.close()\n\n    def test_request_close(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\nConnection: close\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.read_until_close(callback=self.stop)\n        data = self.wait()\n        self.assertTrue(not data)\n        self.close()\n\n    # keepalive is supported for http 1.0 too, but it's opt-in\n    def test_http10(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.0\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.read_until_close(callback=self.stop)\n        data = self.wait()\n        self.assertTrue(not data)\n        self.assertTrue('Connection' not in self.headers)\n        self.close()\n\n    def test_http10_keepalive(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.close()\n\n    def test_http10_keepalive_extra_crlf(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.close()\n\n    def test_pipelined_requests(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\nGET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.read_response()\n        self.close()\n\n    def test_pipelined_cancel(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\nGET / HTTP/1.1\\r\\n\\r\\n')\n        # only read once\n        self.read_response()\n        self.close()\n\n    def test_cancel_during_download(self):\n        self.connect()\n        self.stream.write(b'GET /large HTTP/1.1\\r\\n\\r\\n')\n        self.read_headers()\n        self.stream.read_bytes(1024, self.stop)\n        self.wait()\n        self.close()\n\n    def test_finish_while_closed(self):\n        self.connect()\n        self.stream.write(b'GET /finish_on_close HTTP/1.1\\r\\n\\r\\n')\n        self.read_headers()\n        self.close()\n\n    def test_keepalive_chunked(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'POST / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n'\n                          b'Transfer-Encoding: chunked\\r\\n'\n                          b'\\r\\n0\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.close()\n\n\nclass GzipBaseTest(object):\n    def get_app(self):\n        return Application([('/', EchoHandler)])\n\n    def post_gzip(self, body):\n        bytesio = BytesIO()\n        gzip_file = gzip.GzipFile(mode='w', fileobj=bytesio)\n        gzip_file.write(utf8(body))\n        gzip_file.close()\n        compressed_body = bytesio.getvalue()\n        return self.fetch('/', method='POST', body=compressed_body,\n                          headers={'Content-Encoding': 'gzip'})\n\n    def test_uncompressed(self):\n        response = self.fetch('/', method='POST', body='foo=bar')\n        self.assertEquals(json_decode(response.body), {u'foo': [u'bar']})\n\n\nclass GzipTest(GzipBaseTest, AsyncHTTPTestCase):\n    def get_httpserver_options(self):\n        return dict(decompress_request=True)\n\n    def test_gzip(self):\n        response = self.post_gzip('foo=bar')\n        self.assertEquals(json_decode(response.body), {u'foo': [u'bar']})\n\n\nclass GzipUnsupportedTest(GzipBaseTest, AsyncHTTPTestCase):\n    def test_gzip_unsupported(self):\n        # Gzip support is opt-in; without it the server fails to parse\n        # the body (but parsing form bodies is currently just a log message,\n        # not a fatal error).\n        with ExpectLog(gen_log, \"Unsupported Content-Encoding\"):\n            response = self.post_gzip('foo=bar')\n        self.assertEquals(json_decode(response.body), {})\n\n\nclass StreamingChunkSizeTest(AsyncHTTPTestCase):\n    # 50 characters long, and repetitive so it can be compressed.\n    BODY = b'01234567890123456789012345678901234567890123456789'\n    CHUNK_SIZE = 16\n\n    def get_http_client(self):\n        # body_producer doesn't work on curl_httpclient, so override the\n        # configured AsyncHTTPClient implementation.\n        return SimpleAsyncHTTPClient(io_loop=self.io_loop)\n\n    def get_httpserver_options(self):\n        return dict(chunk_size=self.CHUNK_SIZE, decompress_request=True)\n\n    class MessageDelegate(HTTPMessageDelegate):\n        def __init__(self, connection):\n            self.connection = connection\n\n        def headers_received(self, start_line, headers):\n            self.chunk_lengths = []\n\n        def data_received(self, chunk):\n            self.chunk_lengths.append(len(chunk))\n\n        def finish(self):\n            response_body = utf8(json_encode(self.chunk_lengths))\n            self.connection.write_headers(\n                ResponseStartLine('HTTP/1.1', 200, 'OK'),\n                HTTPHeaders({'Content-Length': str(len(response_body))}))\n            self.connection.write(response_body)\n            self.connection.finish()\n\n    def get_app(self):\n        class App(HTTPServerConnectionDelegate):\n            def start_request(self, server_conn, request_conn):\n                return StreamingChunkSizeTest.MessageDelegate(request_conn)\n        return App()\n\n    def fetch_chunk_sizes(self, **kwargs):\n        response = self.fetch('/', method='POST', **kwargs)\n        response.rethrow()\n        chunks = json_decode(response.body)\n        self.assertEqual(len(self.BODY), sum(chunks))\n        for chunk_size in chunks:\n            self.assertLessEqual(chunk_size, self.CHUNK_SIZE,\n                                 'oversized chunk: ' + str(chunks))\n            self.assertGreater(chunk_size, 0,\n                               'empty chunk: ' + str(chunks))\n        return chunks\n\n    def compress(self, body):\n        bytesio = BytesIO()\n        gzfile = gzip.GzipFile(mode='w', fileobj=bytesio)\n        gzfile.write(body)\n        gzfile.close()\n        compressed = bytesio.getvalue()\n        if len(compressed) >= len(body):\n            raise Exception(\"body did not shrink when compressed\")\n        return compressed\n\n    def test_regular_body(self):\n        chunks = self.fetch_chunk_sizes(body=self.BODY)\n        # Without compression we know exactly what to expect.\n        self.assertEqual([16, 16, 16, 2], chunks)\n\n    def test_compressed_body(self):\n        self.fetch_chunk_sizes(body=self.compress(self.BODY),\n                               headers={'Content-Encoding': 'gzip'})\n        # Compression creates irregular boundaries so the assertions\n        # in fetch_chunk_sizes are as specific as we can get.\n\n    def test_chunked_body(self):\n        def body_producer(write):\n            write(self.BODY[:20])\n            write(self.BODY[20:])\n        chunks = self.fetch_chunk_sizes(body_producer=body_producer)\n        # HTTP chunk boundaries translate to application-visible breaks\n        self.assertEqual([16, 4, 16, 14], chunks)\n\n    def test_chunked_compressed(self):\n        compressed = self.compress(self.BODY)\n        self.assertGreater(len(compressed), 20)\n\n        def body_producer(write):\n            write(compressed[:20])\n            write(compressed[20:])\n        self.fetch_chunk_sizes(body_producer=body_producer,\n                               headers={'Content-Encoding': 'gzip'})\n\n\nclass MaxHeaderSizeTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([('/', HelloWorldRequestHandler)])\n\n    def get_httpserver_options(self):\n        return dict(max_header_size=1024)\n\n    def test_small_headers(self):\n        response = self.fetch(\"/\", headers={'X-Filler': 'a' * 100})\n        response.rethrow()\n        self.assertEqual(response.body, b\"Hello world\")\n\n    def test_large_headers(self):\n        with ExpectLog(gen_log, \"Unsatisfiable read\", required=False):\n            response = self.fetch(\"/\", headers={'X-Filler': 'a' * 1000})\n        # 431 is \"Request Header Fields Too Large\", defined in RFC\n        # 6585. However, many implementations just close the\n        # connection in this case, resulting in a 599.\n        self.assertIn(response.code, (431, 599))\n\n\n@skipOnTravis\nclass IdleTimeoutTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([('/', HelloWorldRequestHandler)])\n\n    def get_httpserver_options(self):\n        return dict(idle_connection_timeout=0.1)\n\n    def setUp(self):\n        super(IdleTimeoutTest, self).setUp()\n        self.streams = []\n\n    def tearDown(self):\n        super(IdleTimeoutTest, self).tearDown()\n        for stream in self.streams:\n            stream.close()\n\n    def connect(self):\n        stream = IOStream(socket.socket())\n        stream.connect(('127.0.0.1', self.get_http_port()), self.stop)\n        self.wait()\n        self.streams.append(stream)\n        return stream\n\n    def test_unused_connection(self):\n        stream = self.connect()\n        stream.set_close_callback(self.stop)\n        self.wait()\n\n    def test_idle_after_use(self):\n        stream = self.connect()\n        stream.set_close_callback(lambda: self.stop(\"closed\"))\n\n        # Use the connection twice to make sure keep-alives are working\n        for i in range(2):\n            stream.write(b\"GET / HTTP/1.1\\r\\n\\r\\n\")\n            stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n            self.wait()\n            stream.read_bytes(11, self.stop)\n            data = self.wait()\n            self.assertEqual(data, b\"Hello world\")\n\n        # Now let the timeout trigger and close the connection.\n        data = self.wait()\n        self.assertEqual(data, \"closed\")\n\n\nclass BodyLimitsTest(AsyncHTTPTestCase):\n    def get_app(self):\n        class BufferedHandler(RequestHandler):\n            def put(self):\n                self.write(str(len(self.request.body)))\n\n        @stream_request_body\n        class StreamingHandler(RequestHandler):\n            def initialize(self):\n                self.bytes_read = 0\n\n            def prepare(self):\n                if 'expected_size' in self.request.arguments:\n                    self.request.connection.set_max_body_size(\n                        int(self.get_argument('expected_size')))\n                if 'body_timeout' in self.request.arguments:\n                    self.request.connection.set_body_timeout(\n                        float(self.get_argument('body_timeout')))\n\n            def data_received(self, data):\n                self.bytes_read += len(data)\n\n            def put(self):\n                self.write(str(self.bytes_read))\n\n        return Application([('/buffered', BufferedHandler),\n                            ('/streaming', StreamingHandler)])\n\n    def get_httpserver_options(self):\n        return dict(body_timeout=3600, max_body_size=4096)\n\n    def get_http_client(self):\n        # body_producer doesn't work on curl_httpclient, so override the\n        # configured AsyncHTTPClient implementation.\n        return SimpleAsyncHTTPClient(io_loop=self.io_loop)\n\n    def test_small_body(self):\n        response = self.fetch('/buffered', method='PUT', body=b'a' * 4096)\n        self.assertEqual(response.body, b'4096')\n        response = self.fetch('/streaming', method='PUT', body=b'a' * 4096)\n        self.assertEqual(response.body, b'4096')\n\n    def test_large_body_buffered(self):\n        with ExpectLog(gen_log, '.*Content-Length too long'):\n            response = self.fetch('/buffered', method='PUT', body=b'a' * 10240)\n        self.assertEqual(response.code, 599)\n\n    def test_large_body_buffered_chunked(self):\n        with ExpectLog(gen_log, '.*chunked body too large'):\n            response = self.fetch('/buffered', method='PUT',\n                                  body_producer=lambda write: write(b'a' * 10240))\n        self.assertEqual(response.code, 599)\n\n    def test_large_body_streaming(self):\n        with ExpectLog(gen_log, '.*Content-Length too long'):\n            response = self.fetch('/streaming', method='PUT', body=b'a' * 10240)\n        self.assertEqual(response.code, 599)\n\n    def test_large_body_streaming_chunked(self):\n        with ExpectLog(gen_log, '.*chunked body too large'):\n            response = self.fetch('/streaming', method='PUT',\n                                  body_producer=lambda write: write(b'a' * 10240))\n        self.assertEqual(response.code, 599)\n\n    def test_large_body_streaming_override(self):\n        response = self.fetch('/streaming?expected_size=10240', method='PUT',\n                              body=b'a' * 10240)\n        self.assertEqual(response.body, b'10240')\n\n    def test_large_body_streaming_chunked_override(self):\n        response = self.fetch('/streaming?expected_size=10240', method='PUT',\n                              body_producer=lambda write: write(b'a' * 10240))\n        self.assertEqual(response.body, b'10240')\n\n    @gen_test\n    def test_timeout(self):\n        stream = IOStream(socket.socket())\n        try:\n            yield stream.connect(('127.0.0.1', self.get_http_port()))\n            # Use a raw stream because AsyncHTTPClient won't let us read a\n            # response without finishing a body.\n            stream.write(b'PUT /streaming?body_timeout=0.1 HTTP/1.0\\r\\n'\n                         b'Content-Length: 42\\r\\n\\r\\n')\n            with ExpectLog(gen_log, 'Timeout reading body'):\n                response = yield stream.read_until_close()\n            self.assertEqual(response, b'')\n        finally:\n            stream.close()\n\n    @gen_test\n    def test_body_size_override_reset(self):\n        # The max_body_size override is reset between requests.\n        stream = IOStream(socket.socket())\n        try:\n            yield stream.connect(('127.0.0.1', self.get_http_port()))\n            # Use a raw stream so we can make sure it's all on one connection.\n            stream.write(b'PUT /streaming?expected_size=10240 HTTP/1.1\\r\\n'\n                         b'Content-Length: 10240\\r\\n\\r\\n')\n            stream.write(b'a' * 10240)\n            headers, response = yield gen.Task(read_stream_body, stream)\n            self.assertEqual(response, b'10240')\n            # Without the ?expected_size parameter, we get the old default value\n            stream.write(b'PUT /streaming HTTP/1.1\\r\\n'\n                         b'Content-Length: 10240\\r\\n\\r\\n')\n            with ExpectLog(gen_log, '.*Content-Length too long'):\n                data = yield stream.read_until_close()\n            self.assertEqual(data, b'')\n        finally:\n            stream.close()\n\n\nclass LegacyInterfaceTest(AsyncHTTPTestCase):\n    def get_app(self):\n        # The old request_callback interface does not implement the\n        # delegate interface, and writes its response via request.write\n        # instead of request.connection.write_headers.\n        def handle_request(request):\n            self.http1 = request.version.startswith(\"HTTP/1.\")\n            if not self.http1:\n                # This test will be skipped if we're using HTTP/2,\n                # so just close it out cleanly using the modern interface.\n                request.connection.write_headers(\n                    ResponseStartLine('', 200, 'OK'),\n                    HTTPHeaders())\n                request.connection.finish()\n                return\n            message = b\"Hello world\"\n            request.write(utf8(\"HTTP/1.1 200 OK\\r\\n\"\n                               \"Content-Length: %d\\r\\n\\r\\n\" % len(message)))\n            request.write(message)\n            request.finish()\n        return handle_request\n\n    def test_legacy_interface(self):\n        response = self.fetch('/')\n        if not self.http1:\n            self.skipTest(\"requires HTTP/1.x\")\n        self.assertEqual(response.body, b\"Hello world\")\n",
            "header": {
                "file": {
                    "path": "tornado/test/httpserver_test.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "27052e69",
                "new_commit_hash": "4923152b",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tornado/test/httpserver_test.py"
            },
            "plus_file": {
                "path": "b/tornado/test/httpserver_test.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 436,
                            "length": 6
                        },
                        "new_range": {
                            "start": 436,
                            "length": 25
                        },
                        "section": "foo="
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "bar",
                                "type": "context"
                            },
                            {
                                "content": "0",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "\"\"\".replace(b\"\\n\", b\"\\r\\n\"))",
                                "type": "added"
                            },
                            {
                                "content": "        read_stream_body(self.stream, self.stop)",
                                "type": "added"
                            },
                            {
                                "content": "        headers, response = self.wait()",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertEqual(json_decode(response), {u'foo': [u'bar']})",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    def test_chunked_request_uppercase(self):",
                                "type": "added"
                            },
                            {
                                "content": "        # As per RFC 2616 section 3.6, \"Transfer-Encoding\" header's value is",
                                "type": "added"
                            },
                            {
                                "content": "        # case-insensitive.",
                                "type": "added"
                            },
                            {
                                "content": "        self.stream.write(b\"\"\"\\",
                                "type": "added"
                            },
                            {
                                "content": "POST /echo HTTP/1.1",
                                "type": "added"
                            },
                            {
                                "content": "Transfer-Encoding: Chunked",
                                "type": "added"
                            },
                            {
                                "content": "Content-Type: application/x-www-form-urlencoded",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "4",
                                "type": "added"
                            },
                            {
                                "content": "foo=",
                                "type": "added"
                            },
                            {
                                "content": "3",
                                "type": "added"
                            },
                            {
                                "content": "bar",
                                "type": "added"
                            },
                            {
                                "content": "0",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "\"\"\".replace(b\"\\n\", b\"\\r\\n\"))",
                                "type": "context"
                            },
                            {
                                "content": "        read_stream_body(self.stream, self.stop)",
                                "type": "context"
                            },
                            {
                                "content": "        headers, response = self.wait()",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/test/httpserver_test.py",
                            "type": "class",
                            "name": "HTTPServerRawTest",
                            "content": "class HTTPServerRawTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([\n            ('/echo', EchoHandler),\n        ])\n\n    def setUp(self):\n        super(HTTPServerRawTest, self).setUp()\n        self.stream = IOStream(socket.socket())\n        self.stream.connect(('127.0.0.1', self.get_http_port()), self.stop)\n        self.wait()\n\n    def tearDown(self):\n        self.stream.close()\n        super(HTTPServerRawTest, self).tearDown()\n\n    def test_empty_request(self):\n        self.stream.close()\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()\n\n    def test_malformed_first_line(self):\n        with ExpectLog(gen_log, '.*Malformed HTTP request line'):\n            self.stream.write(b'asdf\\r\\n\\r\\n')\n            # TODO: need an async version of ExpectLog so we don't need\n            # hard-coded timeouts here.\n            self.io_loop.add_timeout(datetime.timedelta(seconds=0.01),\n                                     self.stop)\n            self.wait()\n\n    def test_malformed_headers(self):\n        with ExpectLog(gen_log, '.*Malformed HTTP headers'):\n            self.stream.write(b'GET / HTTP/1.0\\r\\nasdf\\r\\n\\r\\n')\n            self.io_loop.add_timeout(datetime.timedelta(seconds=0.01),\n                                     self.stop)\n            self.wait()\n\n    def test_chunked_request_body(self):\n        # Chunked requests are not widely supported and we don't have a way\n        # to generate them in AsyncHTTPClient, but HTTPServer will read them.\n        self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nTransfer-Encoding: chunked\nContent-Type: application/x-www-form-urlencoded\n\n4\nfoo=\n3\nbar\n0\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n        read_stream_body(self.stream, self.stop)\n        headers, response = self.wait()\n        self.assertEqual(json_decode(response), {u'foo': [u'bar']})\n\n    def test_chunked_request_uppercase(self):\n        # As per RFC 2616 section 3.6, \"Transfer-Encoding\" header's value is\n        # case-insensitive.\n        self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nTransfer-Encoding: Chunked\nContent-Type: application/x-www-form-urlencoded\n\n4\nfoo=\n3\nbar\n0\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n        read_stream_body(self.stream, self.stop)\n        headers, response = self.wait()\n        self.assertEqual(json_decode(response), {u'foo': [u'bar']})\n\n    def test_invalid_content_length(self):\n        with ExpectLog(gen_log, '.*Only integer Content-Length is allowed'):\n            self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nContent-Length: foo\n\nbar\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n            self.stream.read_until_close(self.stop)\n            self.wait()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 388,
                            "end_lineno": 473,
                            "parent": null
                        },
                        {
                            "file_name": "tornado/test/httpserver_test.py",
                            "type": "method",
                            "name": "HTTPServerRawTest.test_chunked_request_body",
                            "content": "class HTTPServerRawTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([\n            ('/echo', EchoHandler),\n        ])\n\n    def setUp(self):\n        super(HTTPServerRawTest, self).setUp()\n        self.stream = IOStream(socket.socket())\n        self.stream.connect(('127.0.0.1', self.get_http_port()), self.stop)\n        self.wait()\n\n    def tearDown(self):\n        self.stream.close()\n        super(HTTPServerRawTest, self).tearDown()\n\n    def test_empty_request(self):\n        self.stream.close()\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()\n\n    def test_malformed_first_line(self):\n        with ExpectLog(gen_log, '.*Malformed HTTP request line'):\n            self.stream.write(b'asdf\\r\\n\\r\\n')\n            # TODO: need an async version of ExpectLog so we don't need\n            # hard-coded timeouts here.\n            self.io_loop.add_timeout(datetime.timedelta(seconds=0.01),\n                                     self.stop)\n            self.wait()\n\n    def test_malformed_headers(self):\n        with ExpectLog(gen_log, '.*Malformed HTTP headers'):\n            self.stream.write(b'GET / HTTP/1.0\\r\\nasdf\\r\\n\\r\\n')\n            self.io_loop.add_timeout(datetime.timedelta(seconds=0.01),\n                                     self.stop)\n            self.wait()\n\n    def test_chunked_request_body(self):\n        # Chunked requests are not widely supported and we don't have a way\n        # to generate them in AsyncHTTPClient, but HTTPServer will read them.\n        self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nTransfer-Encoding: chunked\nContent-Type: application/x-www-form-urlencoded\n\n4\nfoo=\n3\nbar\n0\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n        read_stream_body(self.stream, self.stop)\n        headers, response = self.wait()\n        self.assertEqual(json_decode(response), {u'foo': [u'bar']})\n\n    def test_chunked_request_uppercase(self):\n        # As per RFC 2616 section 3.6, \"Transfer-Encoding\" header's value is\n        # case-insensitive.\n        self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nTransfer-Encoding: Chunked\nContent-Type: application/x-www-form-urlencoded\n\n4\nfoo=\n3\nbar\n0\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n        read_stream_body(self.stream, self.stop)\n        headers, response = self.wait()\n        self.assertEqual(json_decode(response), {u'foo': [u'bar']})\n\n    def test_invalid_content_length(self):\n        with ExpectLog(gen_log, '.*Only integer Content-Length is allowed'):\n            self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nContent-Length: foo\n\nbar\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n            self.stream.read_until_close(self.stop)\n            self.wait()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 425,
                            "end_lineno": 442,
                            "parent": {
                                "file_name": "tornado/test/httpserver_test.py",
                                "type": "class",
                                "name": "HTTPServerRawTest",
                                "content": "class HTTPServerRawTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([\n            ('/echo', EchoHandler),\n        ])\n\n    def setUp(self):\n        super(HTTPServerRawTest, self).setUp()\n        self.stream = IOStream(socket.socket())\n        self.stream.connect(('127.0.0.1', self.get_http_port()), self.stop)\n        self.wait()\n\n    def tearDown(self):\n        self.stream.close()\n        super(HTTPServerRawTest, self).tearDown()\n\n    def test_empty_request(self):\n        self.stream.close()\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()\n\n    def test_malformed_first_line(self):\n        with ExpectLog(gen_log, '.*Malformed HTTP request line'):\n            self.stream.write(b'asdf\\r\\n\\r\\n')\n            # TODO: need an async version of ExpectLog so we don't need\n            # hard-coded timeouts here.\n            self.io_loop.add_timeout(datetime.timedelta(seconds=0.01),\n                                     self.stop)\n            self.wait()\n\n    def test_malformed_headers(self):\n        with ExpectLog(gen_log, '.*Malformed HTTP headers'):\n            self.stream.write(b'GET / HTTP/1.0\\r\\nasdf\\r\\n\\r\\n')\n            self.io_loop.add_timeout(datetime.timedelta(seconds=0.01),\n                                     self.stop)\n            self.wait()\n\n    def test_chunked_request_body(self):\n        # Chunked requests are not widely supported and we don't have a way\n        # to generate them in AsyncHTTPClient, but HTTPServer will read them.\n        self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nTransfer-Encoding: chunked\nContent-Type: application/x-www-form-urlencoded\n\n4\nfoo=\n3\nbar\n0\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n        read_stream_body(self.stream, self.stop)\n        headers, response = self.wait()\n        self.assertEqual(json_decode(response), {u'foo': [u'bar']})\n\n    def test_chunked_request_uppercase(self):\n        # As per RFC 2616 section 3.6, \"Transfer-Encoding\" header's value is\n        # case-insensitive.\n        self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nTransfer-Encoding: Chunked\nContent-Type: application/x-www-form-urlencoded\n\n4\nfoo=\n3\nbar\n0\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n        read_stream_body(self.stream, self.stop)\n        headers, response = self.wait()\n        self.assertEqual(json_decode(response), {u'foo': [u'bar']})\n\n    def test_invalid_content_length(self):\n        with ExpectLog(gen_log, '.*Only integer Content-Length is allowed'):\n            self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nContent-Length: foo\n\nbar\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n            self.stream.read_until_close(self.stop)\n            self.wait()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 388,
                                "end_lineno": 473,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [
                        {
                            "file_name": "tornado/test/httpserver_test.py",
                            "type": "method",
                            "name": "HTTPServerRawTest.test_chunked_request_uppercase",
                            "content": "class HTTPServerRawTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([\n            ('/echo', EchoHandler),\n        ])\n\n    def setUp(self):\n        super(HTTPServerRawTest, self).setUp()\n        self.stream = IOStream(socket.socket())\n        self.stream.connect(('127.0.0.1', self.get_http_port()), self.stop)\n        self.wait()\n\n    def tearDown(self):\n        self.stream.close()\n        super(HTTPServerRawTest, self).tearDown()\n\n    def test_empty_request(self):\n        self.stream.close()\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()\n\n    def test_malformed_first_line(self):\n        with ExpectLog(gen_log, '.*Malformed HTTP request line'):\n            self.stream.write(b'asdf\\r\\n\\r\\n')\n            # TODO: need an async version of ExpectLog so we don't need\n            # hard-coded timeouts here.\n            self.io_loop.add_timeout(datetime.timedelta(seconds=0.01),\n                                     self.stop)\n            self.wait()\n\n    def test_malformed_headers(self):\n        with ExpectLog(gen_log, '.*Malformed HTTP headers'):\n            self.stream.write(b'GET / HTTP/1.0\\r\\nasdf\\r\\n\\r\\n')\n            self.io_loop.add_timeout(datetime.timedelta(seconds=0.01),\n                                     self.stop)\n            self.wait()\n\n    def test_chunked_request_body(self):\n        # Chunked requests are not widely supported and we don't have a way\n        # to generate them in AsyncHTTPClient, but HTTPServer will read them.\n        self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nTransfer-Encoding: chunked\nContent-Type: application/x-www-form-urlencoded\n\n4\nfoo=\n3\nbar\n0\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n        read_stream_body(self.stream, self.stop)\n        headers, response = self.wait()\n        self.assertEqual(json_decode(response), {u'foo': [u'bar']})\n\n    def test_chunked_request_uppercase(self):\n        # As per RFC 2616 section 3.6, \"Transfer-Encoding\" header's value is\n        # case-insensitive.\n        self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nTransfer-Encoding: Chunked\nContent-Type: application/x-www-form-urlencoded\n\n4\nfoo=\n3\nbar\n0\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n        read_stream_body(self.stream, self.stop)\n        headers, response = self.wait()\n        self.assertEqual(json_decode(response), {u'foo': [u'bar']})\n\n    def test_invalid_content_length(self):\n        with ExpectLog(gen_log, '.*Only integer Content-Length is allowed'):\n            self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nContent-Length: foo\n\nbar\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n            self.stream.read_until_close(self.stop)\n            self.wait()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 444,
                            "end_lineno": 461,
                            "parent": {
                                "file_name": "tornado/test/httpserver_test.py",
                                "type": "class",
                                "name": "HTTPServerRawTest",
                                "content": "class HTTPServerRawTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([\n            ('/echo', EchoHandler),\n        ])\n\n    def setUp(self):\n        super(HTTPServerRawTest, self).setUp()\n        self.stream = IOStream(socket.socket())\n        self.stream.connect(('127.0.0.1', self.get_http_port()), self.stop)\n        self.wait()\n\n    def tearDown(self):\n        self.stream.close()\n        super(HTTPServerRawTest, self).tearDown()\n\n    def test_empty_request(self):\n        self.stream.close()\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()\n\n    def test_malformed_first_line(self):\n        with ExpectLog(gen_log, '.*Malformed HTTP request line'):\n            self.stream.write(b'asdf\\r\\n\\r\\n')\n            # TODO: need an async version of ExpectLog so we don't need\n            # hard-coded timeouts here.\n            self.io_loop.add_timeout(datetime.timedelta(seconds=0.01),\n                                     self.stop)\n            self.wait()\n\n    def test_malformed_headers(self):\n        with ExpectLog(gen_log, '.*Malformed HTTP headers'):\n            self.stream.write(b'GET / HTTP/1.0\\r\\nasdf\\r\\n\\r\\n')\n            self.io_loop.add_timeout(datetime.timedelta(seconds=0.01),\n                                     self.stop)\n            self.wait()\n\n    def test_chunked_request_body(self):\n        # Chunked requests are not widely supported and we don't have a way\n        # to generate them in AsyncHTTPClient, but HTTPServer will read them.\n        self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nTransfer-Encoding: chunked\nContent-Type: application/x-www-form-urlencoded\n\n4\nfoo=\n3\nbar\n0\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n        read_stream_body(self.stream, self.stop)\n        headers, response = self.wait()\n        self.assertEqual(json_decode(response), {u'foo': [u'bar']})\n\n    def test_chunked_request_uppercase(self):\n        # As per RFC 2616 section 3.6, \"Transfer-Encoding\" header's value is\n        # case-insensitive.\n        self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nTransfer-Encoding: Chunked\nContent-Type: application/x-www-form-urlencoded\n\n4\nfoo=\n3\nbar\n0\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n        read_stream_body(self.stream, self.stop)\n        headers, response = self.wait()\n        self.assertEqual(json_decode(response), {u'foo': [u'bar']})\n\n    def test_invalid_content_length(self):\n        with ExpectLog(gen_log, '.*Only integer Content-Length is allowed'):\n            self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nContent-Length: foo\n\nbar\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n            self.stream.read_until_close(self.stop)\n            self.wait()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 388,
                                "end_lineno": 473,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "613299c6d4f705e3145847ebc88b3dd6f9bb3579^",
    "new_commit_hash": "613299c6d4f705e3145847ebc88b3dd6f9bb3579",
    "commit_message": "Merge pull request #1778 from protoss-player/master\n\nFix for uppercase \"Transfer-Encoding\" values",
    "commit_date": "2016-07-24T21:35:46-04:00",
    "metadata": {}
}
{
    "repo_name": "tornado",
    "new_commit_hash": "613299c6d4f705e3145847ebc88b3dd6f9bb3579",
    "test_file_codes": [
        "#!/usr/bin/env python\n\n\nfrom __future__ import absolute_import, division, print_function, with_statement\nfrom tornado import netutil\nfrom tornado.escape import json_decode, json_encode, utf8, _unicode, recursive_unicode, native_str\nfrom tornado import gen\nfrom tornado.http1connection import HTTP1Connection\nfrom tornado.httpserver import HTTPServer\nfrom tornado.httputil import HTTPHeaders, HTTPMessageDelegate, HTTPServerConnectionDelegate, ResponseStartLine\nfrom tornado.iostream import IOStream\nfrom tornado.log import gen_log\nfrom tornado.netutil import ssl_options_to_context\nfrom tornado.simple_httpclient import SimpleAsyncHTTPClient\nfrom tornado.testing import AsyncHTTPTestCase, AsyncHTTPSTestCase, AsyncTestCase, ExpectLog, gen_test\nfrom tornado.test.util import unittest, skipOnTravis\nfrom tornado.web import Application, RequestHandler, asynchronous, stream_request_body\nfrom contextlib import closing\nimport datetime\nimport gzip\nimport os\nimport shutil\nimport socket\nimport ssl\nimport sys\nimport tempfile\nfrom io import BytesIO\n\n\ndef read_stream_body(stream, callback):\n    \"\"\"Reads an HTTP response from `stream` and runs callback with its\n    headers and body.\"\"\"\n    chunks = []\n\n    class Delegate(HTTPMessageDelegate):\n        def headers_received(self, start_line, headers):\n            self.headers = headers\n\n        def data_received(self, chunk):\n            chunks.append(chunk)\n\n        def finish(self):\n            callback((self.headers, b''.join(chunks)))\n    conn = HTTP1Connection(stream, True)\n    conn.read_response(Delegate())\n\n\nclass HandlerBaseTestCase(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([('/', self.__class__.Handler)])\n\n    def fetch_json(self, *args, **kwargs):\n        response = self.fetch(*args, **kwargs)\n        response.rethrow()\n        return json_decode(response.body)\n\n\nclass HelloWorldRequestHandler(RequestHandler):\n    def initialize(self, protocol=\"http\"):\n        self.expected_protocol = protocol\n\n    def get(self):\n        if self.request.protocol != self.expected_protocol:\n            raise Exception(\"unexpected protocol\")\n        self.finish(\"Hello world\")\n\n    def post(self):\n        self.finish(\"Got %d bytes in POST\" % len(self.request.body))\n\n\n# In pre-1.0 versions of openssl, SSLv23 clients always send SSLv2\n# ClientHello messages, which are rejected by SSLv3 and TLSv1\n# servers.  Note that while the OPENSSL_VERSION_INFO was formally\n# introduced in python3.2, it was present but undocumented in\n# python 2.7\nskipIfOldSSL = unittest.skipIf(\n    getattr(ssl, 'OPENSSL_VERSION_INFO', (0, 0)) < (1, 0),\n    \"old version of ssl module and/or openssl\")\n\n\nclass BaseSSLTest(AsyncHTTPSTestCase):\n    def get_app(self):\n        return Application([('/', HelloWorldRequestHandler,\n                             dict(protocol=\"https\"))])\n\n\nclass SSLTestMixin(object):\n    def get_ssl_options(self):\n        return dict(ssl_version=self.get_ssl_version(),  # type: ignore\n                    **AsyncHTTPSTestCase.get_ssl_options())\n\n    def get_ssl_version(self):\n        raise NotImplementedError()\n\n    def test_ssl(self):\n        response = self.fetch('/')\n        self.assertEqual(response.body, b\"Hello world\")\n\n    def test_large_post(self):\n        response = self.fetch('/',\n                              method='POST',\n                              body='A' * 5000)\n        self.assertEqual(response.body, b\"Got 5000 bytes in POST\")\n\n    def test_non_ssl_request(self):\n        # Make sure the server closes the connection when it gets a non-ssl\n        # connection, rather than waiting for a timeout or otherwise\n        # misbehaving.\n        with ExpectLog(gen_log, '(SSL Error|uncaught exception)'):\n            with ExpectLog(gen_log, 'Uncaught exception', required=False):\n                self.http_client.fetch(\n                    self.get_url(\"/\").replace('https:', 'http:'),\n                    self.stop,\n                    request_timeout=3600,\n                    connect_timeout=3600)\n                response = self.wait()\n        self.assertEqual(response.code, 599)\n\n    def test_error_logging(self):\n        # No stack traces are logged for SSL errors.\n        with ExpectLog(gen_log, 'SSL Error') as expect_log:\n            self.http_client.fetch(\n                self.get_url(\"/\").replace(\"https:\", \"http:\"),\n                self.stop)\n            response = self.wait()\n            self.assertEqual(response.code, 599)\n        self.assertFalse(expect_log.logged_stack)\n\n# Python's SSL implementation differs significantly between versions.\n# For example, SSLv3 and TLSv1 throw an exception if you try to read\n# from the socket before the handshake is complete, but the default\n# of SSLv23 allows it.\n\n\nclass SSLv23Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_SSLv23\n\n\n@skipIfOldSSL\nclass SSLv3Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_SSLv3\n\n\n@skipIfOldSSL\nclass TLSv1Test(BaseSSLTest, SSLTestMixin):\n    def get_ssl_version(self):\n        return ssl.PROTOCOL_TLSv1\n\n\n@unittest.skipIf(not hasattr(ssl, 'SSLContext'), 'ssl.SSLContext not present')\nclass SSLContextTest(BaseSSLTest, SSLTestMixin):\n    def get_ssl_options(self):\n        context = ssl_options_to_context(\n            AsyncHTTPSTestCase.get_ssl_options(self))\n        assert isinstance(context, ssl.SSLContext)\n        return context\n\n\nclass BadSSLOptionsTest(unittest.TestCase):\n    def test_missing_arguments(self):\n        application = Application()\n        self.assertRaises(KeyError, HTTPServer, application, ssl_options={\n            \"keyfile\": \"/__missing__.crt\",\n        })\n\n    def test_missing_key(self):\n        \"\"\"A missing SSL key should cause an immediate exception.\"\"\"\n\n        application = Application()\n        module_dir = os.path.dirname(__file__)\n        existing_certificate = os.path.join(module_dir, 'test.crt')\n        existing_key = os.path.join(module_dir, 'test.key')\n\n        self.assertRaises((ValueError, IOError),\n                          HTTPServer, application, ssl_options={\n                              \"certfile\": \"/__mising__.crt\",\n        })\n        self.assertRaises((ValueError, IOError),\n                          HTTPServer, application, ssl_options={\n                              \"certfile\": existing_certificate,\n                              \"keyfile\": \"/__missing__.key\"\n        })\n\n        # This actually works because both files exist\n        HTTPServer(application, ssl_options={\n                   \"certfile\": existing_certificate,\n                   \"keyfile\": existing_key,\n                   })\n\n\nclass MultipartTestHandler(RequestHandler):\n    def post(self):\n        self.finish({\"header\": self.request.headers[\"X-Header-Encoding-Test\"],\n                     \"argument\": self.get_argument(\"argument\"),\n                     \"filename\": self.request.files[\"files\"][0].filename,\n                     \"filebody\": _unicode(self.request.files[\"files\"][0][\"body\"]),\n                     })\n\n\n# This test is also called from wsgi_test\nclass HTTPConnectionTest(AsyncHTTPTestCase):\n    def get_handlers(self):\n        return [(\"/multipart\", MultipartTestHandler),\n                (\"/hello\", HelloWorldRequestHandler)]\n\n    def get_app(self):\n        return Application(self.get_handlers())\n\n    def raw_fetch(self, headers, body, newline=b\"\\r\\n\"):\n        with closing(IOStream(socket.socket())) as stream:\n            stream.connect(('127.0.0.1', self.get_http_port()), self.stop)\n            self.wait()\n            stream.write(\n                newline.join(headers +\n                             [utf8(\"Content-Length: %d\" % len(body))]) +\n                newline + newline + body)\n            read_stream_body(stream, self.stop)\n            headers, body = self.wait()\n            return body\n\n    def test_multipart_form(self):\n        # Encodings here are tricky:  Headers are latin1, bodies can be\n        # anything (we use utf8 by default).\n        response = self.raw_fetch([\n            b\"POST /multipart HTTP/1.0\",\n            b\"Content-Type: multipart/form-data; boundary=1234567890\",\n            b\"X-Header-encoding-test: \\xe9\",\n        ],\n            b\"\\r\\n\".join([\n                b\"Content-Disposition: form-data; name=argument\",\n                b\"\",\n                u\"\\u00e1\".encode(\"utf-8\"),\n                b\"--1234567890\",\n                u'Content-Disposition: form-data; name=\"files\"; filename=\"\\u00f3\"'.encode(\"utf8\"),\n                b\"\",\n                u\"\\u00fa\".encode(\"utf-8\"),\n                b\"--1234567890--\",\n                b\"\",\n            ]))\n        data = json_decode(response)\n        self.assertEqual(u\"\\u00e9\", data[\"header\"])\n        self.assertEqual(u\"\\u00e1\", data[\"argument\"])\n        self.assertEqual(u\"\\u00f3\", data[\"filename\"])\n        self.assertEqual(u\"\\u00fa\", data[\"filebody\"])\n\n    def test_newlines(self):\n        # We support both CRLF and bare LF as line separators.\n        for newline in (b\"\\r\\n\", b\"\\n\"):\n            response = self.raw_fetch([b\"GET /hello HTTP/1.0\"], b\"\",\n                                      newline=newline)\n            self.assertEqual(response, b'Hello world')\n\n    def test_100_continue(self):\n        # Run through a 100-continue interaction by hand:\n        # When given Expect: 100-continue, we get a 100 response after the\n        # headers, and then the real response after the body.\n        stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        stream.connect((\"127.0.0.1\", self.get_http_port()), callback=self.stop)\n        self.wait()\n        stream.write(b\"\\r\\n\".join([b\"POST /hello HTTP/1.1\",\n                                   b\"Content-Length: 1024\",\n                                   b\"Expect: 100-continue\",\n                                   b\"Connection: close\",\n                                   b\"\\r\\n\"]), callback=self.stop)\n        self.wait()\n        stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        data = self.wait()\n        self.assertTrue(data.startswith(b\"HTTP/1.1 100 \"), data)\n        stream.write(b\"a\" * 1024)\n        stream.read_until(b\"\\r\\n\", self.stop)\n        first_line = self.wait()\n        self.assertTrue(first_line.startswith(b\"HTTP/1.1 200\"), first_line)\n        stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        header_data = self.wait()\n        headers = HTTPHeaders.parse(native_str(header_data.decode('latin1')))\n        stream.read_bytes(int(headers[\"Content-Length\"]), self.stop)\n        body = self.wait()\n        self.assertEqual(body, b\"Got 1024 bytes in POST\")\n        stream.close()\n\n\nclass EchoHandler(RequestHandler):\n    def get(self):\n        self.write(recursive_unicode(self.request.arguments))\n\n    def post(self):\n        self.write(recursive_unicode(self.request.arguments))\n\n\nclass TypeCheckHandler(RequestHandler):\n    def prepare(self):\n        self.errors = {}\n        fields = [\n            ('method', str),\n            ('uri', str),\n            ('version', str),\n            ('remote_ip', str),\n            ('protocol', str),\n            ('host', str),\n            ('path', str),\n            ('query', str),\n        ]\n        for field, expected_type in fields:\n            self.check_type(field, getattr(self.request, field), expected_type)\n\n        self.check_type('header_key', list(self.request.headers.keys())[0], str)\n        self.check_type('header_value', list(self.request.headers.values())[0], str)\n\n        self.check_type('cookie_key', list(self.request.cookies.keys())[0], str)\n        self.check_type('cookie_value', list(self.request.cookies.values())[0].value, str)\n        # secure cookies\n\n        self.check_type('arg_key', list(self.request.arguments.keys())[0], str)\n        self.check_type('arg_value', list(self.request.arguments.values())[0][0], bytes)\n\n    def post(self):\n        self.check_type('body', self.request.body, bytes)\n        self.write(self.errors)\n\n    def get(self):\n        self.write(self.errors)\n\n    def check_type(self, name, obj, expected_type):\n        actual_type = type(obj)\n        if expected_type != actual_type:\n            self.errors[name] = \"expected %s, got %s\" % (expected_type,\n                                                         actual_type)\n\n\nclass HTTPServerTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([(\"/echo\", EchoHandler),\n                            (\"/typecheck\", TypeCheckHandler),\n                            (\"//doubleslash\", EchoHandler),\n                            ])\n\n    def test_query_string_encoding(self):\n        response = self.fetch(\"/echo?foo=%C3%A9\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u\"foo\": [u\"\\u00e9\"]})\n\n    def test_empty_query_string(self):\n        response = self.fetch(\"/echo?foo=&foo=\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u\"foo\": [u\"\", u\"\"]})\n\n    def test_empty_post_parameters(self):\n        response = self.fetch(\"/echo\", method=\"POST\", body=\"foo=&bar=\")\n        data = json_decode(response.body)\n        self.assertEqual(data, {u\"foo\": [u\"\"], u\"bar\": [u\"\"]})\n\n    def test_types(self):\n        headers = {\"Cookie\": \"foo=bar\"}\n        response = self.fetch(\"/typecheck?foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n        response = self.fetch(\"/typecheck\", method=\"POST\", body=\"foo=bar\", headers=headers)\n        data = json_decode(response.body)\n        self.assertEqual(data, {})\n\n    def test_double_slash(self):\n        # urlparse.urlsplit (which tornado.httpserver used to use\n        # incorrectly) would parse paths beginning with \"//\" as\n        # protocol-relative urls.\n        response = self.fetch(\"//doubleslash\")\n        self.assertEqual(200, response.code)\n        self.assertEqual(json_decode(response.body), {})\n\n    def test_malformed_body(self):\n        # parse_qs is pretty forgiving, but it will fail on python 3\n        # if the data is not utf8.  On python 2 parse_qs will work,\n        # but then the recursive_unicode call in EchoHandler will\n        # fail.\n        if str is bytes:\n            return\n        with ExpectLog(gen_log, 'Invalid x-www-form-urlencoded body'):\n            response = self.fetch(\n                '/echo', method=\"POST\",\n                headers={'Content-Type': 'application/x-www-form-urlencoded'},\n                body=b'\\xe9')\n        self.assertEqual(200, response.code)\n        self.assertEqual(b'{}', response.body)\n\n\nclass HTTPServerRawTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([\n            ('/echo', EchoHandler),\n        ])\n\n    def setUp(self):\n        super(HTTPServerRawTest, self).setUp()\n        self.stream = IOStream(socket.socket())\n        self.stream.connect(('127.0.0.1', self.get_http_port()), self.stop)\n        self.wait()\n\n    def tearDown(self):\n        self.stream.close()\n        super(HTTPServerRawTest, self).tearDown()\n\n    def test_empty_request(self):\n        self.stream.close()\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()\n\n    def test_malformed_first_line(self):\n        with ExpectLog(gen_log, '.*Malformed HTTP request line'):\n            self.stream.write(b'asdf\\r\\n\\r\\n')\n            # TODO: need an async version of ExpectLog so we don't need\n            # hard-coded timeouts here.\n            self.io_loop.add_timeout(datetime.timedelta(seconds=0.01),\n                                     self.stop)\n            self.wait()\n\n    def test_malformed_headers(self):\n        with ExpectLog(gen_log, '.*Malformed HTTP headers'):\n            self.stream.write(b'GET / HTTP/1.0\\r\\nasdf\\r\\n\\r\\n')\n            self.io_loop.add_timeout(datetime.timedelta(seconds=0.01),\n                                     self.stop)\n            self.wait()\n\n    def test_chunked_request_body(self):\n        # Chunked requests are not widely supported and we don't have a way\n        # to generate them in AsyncHTTPClient, but HTTPServer will read them.\n        self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nTransfer-Encoding: chunked\nContent-Type: application/x-www-form-urlencoded\n\n4\nfoo=\n3\nbar\n0\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n        read_stream_body(self.stream, self.stop)\n        headers, response = self.wait()\n        self.assertEqual(json_decode(response), {u'foo': [u'bar']})\n\n    def test_chunked_request_uppercase(self):\n        # As per RFC 2616 section 3.6, \"Transfer-Encoding\" header's value is\n        # case-insensitive.\n        self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nTransfer-Encoding: Chunked\nContent-Type: application/x-www-form-urlencoded\n\n4\nfoo=\n3\nbar\n0\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n        read_stream_body(self.stream, self.stop)\n        headers, response = self.wait()\n        self.assertEqual(json_decode(response), {u'foo': [u'bar']})\n\n    def test_invalid_content_length(self):\n        with ExpectLog(gen_log, '.*Only integer Content-Length is allowed'):\n            self.stream.write(b\"\"\"\\\nPOST /echo HTTP/1.1\nContent-Length: foo\n\nbar\n\n\"\"\".replace(b\"\\n\", b\"\\r\\n\"))\n            self.stream.read_until_close(self.stop)\n            self.wait()\n\n\nclass XHeaderTest(HandlerBaseTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(dict(remote_ip=self.request.remote_ip,\n                            remote_protocol=self.request.protocol))\n\n    def get_httpserver_options(self):\n        return dict(xheaders=True)\n\n    def test_ip_headers(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_ip\"], \"127.0.0.1\")\n\n        valid_ipv4 = {\"X-Real-IP\": \"4.4.4.4\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv4)[\"remote_ip\"],\n            \"4.4.4.4\")\n\n        valid_ipv4_list = {\"X-Forwarded-For\": \"127.0.0.1, 4.4.4.4\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv4_list)[\"remote_ip\"],\n            \"4.4.4.4\")\n\n        valid_ipv6 = {\"X-Real-IP\": \"2620:0:1cfe:face:b00c::3\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv6)[\"remote_ip\"],\n            \"2620:0:1cfe:face:b00c::3\")\n\n        valid_ipv6_list = {\"X-Forwarded-For\": \"::1, 2620:0:1cfe:face:b00c::3\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=valid_ipv6_list)[\"remote_ip\"],\n            \"2620:0:1cfe:face:b00c::3\")\n\n        invalid_chars = {\"X-Real-IP\": \"4.4.4.4<script>\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=invalid_chars)[\"remote_ip\"],\n            \"127.0.0.1\")\n\n        invalid_chars_list = {\"X-Forwarded-For\": \"4.4.4.4, 5.5.5.5<script>\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=invalid_chars_list)[\"remote_ip\"],\n            \"127.0.0.1\")\n\n        invalid_host = {\"X-Real-IP\": \"www.google.com\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=invalid_host)[\"remote_ip\"],\n            \"127.0.0.1\")\n\n    def test_scheme_headers(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_protocol\"], \"http\")\n\n        https_scheme = {\"X-Scheme\": \"https\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=https_scheme)[\"remote_protocol\"],\n            \"https\")\n\n        https_forwarded = {\"X-Forwarded-Proto\": \"https\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=https_forwarded)[\"remote_protocol\"],\n            \"https\")\n\n        bad_forwarded = {\"X-Forwarded-Proto\": \"unknown\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=bad_forwarded)[\"remote_protocol\"],\n            \"http\")\n\n\nclass SSLXHeaderTest(AsyncHTTPSTestCase, HandlerBaseTestCase):\n    def get_app(self):\n        return Application([('/', XHeaderTest.Handler)])\n\n    def get_httpserver_options(self):\n        output = super(SSLXHeaderTest, self).get_httpserver_options()\n        output['xheaders'] = True\n        return output\n\n    def test_request_without_xprotocol(self):\n        self.assertEqual(self.fetch_json(\"/\")[\"remote_protocol\"], \"https\")\n\n        http_scheme = {\"X-Scheme\": \"http\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=http_scheme)[\"remote_protocol\"], \"http\")\n\n        bad_scheme = {\"X-Scheme\": \"unknown\"}\n        self.assertEqual(\n            self.fetch_json(\"/\", headers=bad_scheme)[\"remote_protocol\"], \"https\")\n\n\nclass ManualProtocolTest(HandlerBaseTestCase):\n    class Handler(RequestHandler):\n        def get(self):\n            self.write(dict(protocol=self.request.protocol))\n\n    def get_httpserver_options(self):\n        return dict(protocol='https')\n\n    def test_manual_protocol(self):\n        self.assertEqual(self.fetch_json('/')['protocol'], 'https')\n\n\n@unittest.skipIf(not hasattr(socket, 'AF_UNIX') or sys.platform == 'cygwin',\n                 \"unix sockets not supported on this platform\")\nclass UnixSocketTest(AsyncTestCase):\n    \"\"\"HTTPServers can listen on Unix sockets too.\n\n    Why would you want to do this?  Nginx can proxy to backends listening\n    on unix sockets, for one thing (and managing a namespace for unix\n    sockets can be easier than managing a bunch of TCP port numbers).\n\n    Unfortunately, there's no way to specify a unix socket in a url for\n    an HTTP client, so we have to test this by hand.\n    \"\"\"\n    def setUp(self):\n        super(UnixSocketTest, self).setUp()\n        self.tmpdir = tempfile.mkdtemp()\n        self.sockfile = os.path.join(self.tmpdir, \"test.sock\")\n        sock = netutil.bind_unix_socket(self.sockfile)\n        app = Application([(\"/hello\", HelloWorldRequestHandler)])\n        self.server = HTTPServer(app, io_loop=self.io_loop)\n        self.server.add_socket(sock)\n        self.stream = IOStream(socket.socket(socket.AF_UNIX), io_loop=self.io_loop)\n        self.stream.connect(self.sockfile, self.stop)\n        self.wait()\n\n    def tearDown(self):\n        self.stream.close()\n        self.server.stop()\n        shutil.rmtree(self.tmpdir)\n        super(UnixSocketTest, self).tearDown()\n\n    def test_unix_socket(self):\n        self.stream.write(b\"GET /hello HTTP/1.0\\r\\n\\r\\n\")\n        self.stream.read_until(b\"\\r\\n\", self.stop)\n        response = self.wait()\n        self.assertEqual(response, b\"HTTP/1.1 200 OK\\r\\n\")\n        self.stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n        headers = HTTPHeaders.parse(self.wait().decode('latin1'))\n        self.stream.read_bytes(int(headers[\"Content-Length\"]), self.stop)\n        body = self.wait()\n        self.assertEqual(body, b\"Hello world\")\n\n    def test_unix_socket_bad_request(self):\n        # Unix sockets don't have remote addresses so they just return an\n        # empty string.\n        with ExpectLog(gen_log, \"Malformed HTTP message from\"):\n            self.stream.write(b\"garbage\\r\\n\\r\\n\")\n            self.stream.read_until_close(self.stop)\n            response = self.wait()\n        self.assertEqual(response, b\"\")\n\n\nclass KeepAliveTest(AsyncHTTPTestCase):\n    \"\"\"Tests various scenarios for HTTP 1.1 keep-alive support.\n\n    These tests don't use AsyncHTTPClient because we want to control\n    connection reuse and closing.\n    \"\"\"\n    def get_app(self):\n        class HelloHandler(RequestHandler):\n            def get(self):\n                self.finish('Hello world')\n\n            def post(self):\n                self.finish('Hello world')\n\n        class LargeHandler(RequestHandler):\n            def get(self):\n                # 512KB should be bigger than the socket buffers so it will\n                # be written out in chunks.\n                self.write(''.join(chr(i % 256) * 1024 for i in range(512)))\n\n        class FinishOnCloseHandler(RequestHandler):\n            @asynchronous\n            def get(self):\n                self.flush()\n\n            def on_connection_close(self):\n                # This is not very realistic, but finishing the request\n                # from the close callback has the right timing to mimic\n                # some errors seen in the wild.\n                self.finish('closed')\n\n        return Application([('/', HelloHandler),\n                            ('/large', LargeHandler),\n                            ('/finish_on_close', FinishOnCloseHandler)])\n\n    def setUp(self):\n        super(KeepAliveTest, self).setUp()\n        self.http_version = b'HTTP/1.1'\n\n    def tearDown(self):\n        # We just closed the client side of the socket; let the IOLoop run\n        # once to make sure the server side got the message.\n        self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop)\n        self.wait()\n\n        if hasattr(self, 'stream'):\n            self.stream.close()\n        super(KeepAliveTest, self).tearDown()\n\n    # The next few methods are a crude manual http client\n    def connect(self):\n        self.stream = IOStream(socket.socket(), io_loop=self.io_loop)\n        self.stream.connect(('127.0.0.1', self.get_http_port()), self.stop)\n        self.wait()\n\n    def read_headers(self):\n        self.stream.read_until(b'\\r\\n', self.stop)\n        first_line = self.wait()\n        self.assertTrue(first_line.startswith(b'HTTP/1.1 200'), first_line)\n        self.stream.read_until(b'\\r\\n\\r\\n', self.stop)\n        header_bytes = self.wait()\n        headers = HTTPHeaders.parse(header_bytes.decode('latin1'))\n        return headers\n\n    def read_response(self):\n        self.headers = self.read_headers()\n        self.stream.read_bytes(int(self.headers['Content-Length']), self.stop)\n        body = self.wait()\n        self.assertEqual(b'Hello world', body)\n\n    def close(self):\n        self.stream.close()\n        del self.stream\n\n    def test_two_requests(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.close()\n\n    def test_request_close(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\nConnection: close\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.read_until_close(callback=self.stop)\n        data = self.wait()\n        self.assertTrue(not data)\n        self.close()\n\n    # keepalive is supported for http 1.0 too, but it's opt-in\n    def test_http10(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.0\\r\\n\\r\\n')\n        self.read_response()\n        self.stream.read_until_close(callback=self.stop)\n        data = self.wait()\n        self.assertTrue(not data)\n        self.assertTrue('Connection' not in self.headers)\n        self.close()\n\n    def test_http10_keepalive(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.close()\n\n    def test_http10_keepalive_extra_crlf(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.close()\n\n    def test_pipelined_requests(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\nGET / HTTP/1.1\\r\\n\\r\\n')\n        self.read_response()\n        self.read_response()\n        self.close()\n\n    def test_pipelined_cancel(self):\n        self.connect()\n        self.stream.write(b'GET / HTTP/1.1\\r\\n\\r\\nGET / HTTP/1.1\\r\\n\\r\\n')\n        # only read once\n        self.read_response()\n        self.close()\n\n    def test_cancel_during_download(self):\n        self.connect()\n        self.stream.write(b'GET /large HTTP/1.1\\r\\n\\r\\n')\n        self.read_headers()\n        self.stream.read_bytes(1024, self.stop)\n        self.wait()\n        self.close()\n\n    def test_finish_while_closed(self):\n        self.connect()\n        self.stream.write(b'GET /finish_on_close HTTP/1.1\\r\\n\\r\\n')\n        self.read_headers()\n        self.close()\n\n    def test_keepalive_chunked(self):\n        self.http_version = b'HTTP/1.0'\n        self.connect()\n        self.stream.write(b'POST / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n'\n                          b'Transfer-Encoding: chunked\\r\\n'\n                          b'\\r\\n0\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.stream.write(b'GET / HTTP/1.0\\r\\nConnection: keep-alive\\r\\n\\r\\n')\n        self.read_response()\n        self.assertEqual(self.headers['Connection'], 'Keep-Alive')\n        self.close()\n\n\nclass GzipBaseTest(object):\n    def get_app(self):\n        return Application([('/', EchoHandler)])\n\n    def post_gzip(self, body):\n        bytesio = BytesIO()\n        gzip_file = gzip.GzipFile(mode='w', fileobj=bytesio)\n        gzip_file.write(utf8(body))\n        gzip_file.close()\n        compressed_body = bytesio.getvalue()\n        return self.fetch('/', method='POST', body=compressed_body,\n                          headers={'Content-Encoding': 'gzip'})\n\n    def test_uncompressed(self):\n        response = self.fetch('/', method='POST', body='foo=bar')\n        self.assertEquals(json_decode(response.body), {u'foo': [u'bar']})\n\n\nclass GzipTest(GzipBaseTest, AsyncHTTPTestCase):\n    def get_httpserver_options(self):\n        return dict(decompress_request=True)\n\n    def test_gzip(self):\n        response = self.post_gzip('foo=bar')\n        self.assertEquals(json_decode(response.body), {u'foo': [u'bar']})\n\n\nclass GzipUnsupportedTest(GzipBaseTest, AsyncHTTPTestCase):\n    def test_gzip_unsupported(self):\n        # Gzip support is opt-in; without it the server fails to parse\n        # the body (but parsing form bodies is currently just a log message,\n        # not a fatal error).\n        with ExpectLog(gen_log, \"Unsupported Content-Encoding\"):\n            response = self.post_gzip('foo=bar')\n        self.assertEquals(json_decode(response.body), {})\n\n\nclass StreamingChunkSizeTest(AsyncHTTPTestCase):\n    # 50 characters long, and repetitive so it can be compressed.\n    BODY = b'01234567890123456789012345678901234567890123456789'\n    CHUNK_SIZE = 16\n\n    def get_http_client(self):\n        # body_producer doesn't work on curl_httpclient, so override the\n        # configured AsyncHTTPClient implementation.\n        return SimpleAsyncHTTPClient(io_loop=self.io_loop)\n\n    def get_httpserver_options(self):\n        return dict(chunk_size=self.CHUNK_SIZE, decompress_request=True)\n\n    class MessageDelegate(HTTPMessageDelegate):\n        def __init__(self, connection):\n            self.connection = connection\n\n        def headers_received(self, start_line, headers):\n            self.chunk_lengths = []\n\n        def data_received(self, chunk):\n            self.chunk_lengths.append(len(chunk))\n\n        def finish(self):\n            response_body = utf8(json_encode(self.chunk_lengths))\n            self.connection.write_headers(\n                ResponseStartLine('HTTP/1.1', 200, 'OK'),\n                HTTPHeaders({'Content-Length': str(len(response_body))}))\n            self.connection.write(response_body)\n            self.connection.finish()\n\n    def get_app(self):\n        class App(HTTPServerConnectionDelegate):\n            def start_request(self, server_conn, request_conn):\n                return StreamingChunkSizeTest.MessageDelegate(request_conn)\n        return App()\n\n    def fetch_chunk_sizes(self, **kwargs):\n        response = self.fetch('/', method='POST', **kwargs)\n        response.rethrow()\n        chunks = json_decode(response.body)\n        self.assertEqual(len(self.BODY), sum(chunks))\n        for chunk_size in chunks:\n            self.assertLessEqual(chunk_size, self.CHUNK_SIZE,\n                                 'oversized chunk: ' + str(chunks))\n            self.assertGreater(chunk_size, 0,\n                               'empty chunk: ' + str(chunks))\n        return chunks\n\n    def compress(self, body):\n        bytesio = BytesIO()\n        gzfile = gzip.GzipFile(mode='w', fileobj=bytesio)\n        gzfile.write(body)\n        gzfile.close()\n        compressed = bytesio.getvalue()\n        if len(compressed) >= len(body):\n            raise Exception(\"body did not shrink when compressed\")\n        return compressed\n\n    def test_regular_body(self):\n        chunks = self.fetch_chunk_sizes(body=self.BODY)\n        # Without compression we know exactly what to expect.\n        self.assertEqual([16, 16, 16, 2], chunks)\n\n    def test_compressed_body(self):\n        self.fetch_chunk_sizes(body=self.compress(self.BODY),\n                               headers={'Content-Encoding': 'gzip'})\n        # Compression creates irregular boundaries so the assertions\n        # in fetch_chunk_sizes are as specific as we can get.\n\n    def test_chunked_body(self):\n        def body_producer(write):\n            write(self.BODY[:20])\n            write(self.BODY[20:])\n        chunks = self.fetch_chunk_sizes(body_producer=body_producer)\n        # HTTP chunk boundaries translate to application-visible breaks\n        self.assertEqual([16, 4, 16, 14], chunks)\n\n    def test_chunked_compressed(self):\n        compressed = self.compress(self.BODY)\n        self.assertGreater(len(compressed), 20)\n\n        def body_producer(write):\n            write(compressed[:20])\n            write(compressed[20:])\n        self.fetch_chunk_sizes(body_producer=body_producer,\n                               headers={'Content-Encoding': 'gzip'})\n\n\nclass MaxHeaderSizeTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([('/', HelloWorldRequestHandler)])\n\n    def get_httpserver_options(self):\n        return dict(max_header_size=1024)\n\n    def test_small_headers(self):\n        response = self.fetch(\"/\", headers={'X-Filler': 'a' * 100})\n        response.rethrow()\n        self.assertEqual(response.body, b\"Hello world\")\n\n    def test_large_headers(self):\n        with ExpectLog(gen_log, \"Unsatisfiable read\", required=False):\n            response = self.fetch(\"/\", headers={'X-Filler': 'a' * 1000})\n        # 431 is \"Request Header Fields Too Large\", defined in RFC\n        # 6585. However, many implementations just close the\n        # connection in this case, resulting in a 599.\n        self.assertIn(response.code, (431, 599))\n\n\n@skipOnTravis\nclass IdleTimeoutTest(AsyncHTTPTestCase):\n    def get_app(self):\n        return Application([('/', HelloWorldRequestHandler)])\n\n    def get_httpserver_options(self):\n        return dict(idle_connection_timeout=0.1)\n\n    def setUp(self):\n        super(IdleTimeoutTest, self).setUp()\n        self.streams = []\n\n    def tearDown(self):\n        super(IdleTimeoutTest, self).tearDown()\n        for stream in self.streams:\n            stream.close()\n\n    def connect(self):\n        stream = IOStream(socket.socket())\n        stream.connect(('127.0.0.1', self.get_http_port()), self.stop)\n        self.wait()\n        self.streams.append(stream)\n        return stream\n\n    def test_unused_connection(self):\n        stream = self.connect()\n        stream.set_close_callback(self.stop)\n        self.wait()\n\n    def test_idle_after_use(self):\n        stream = self.connect()\n        stream.set_close_callback(lambda: self.stop(\"closed\"))\n\n        # Use the connection twice to make sure keep-alives are working\n        for i in range(2):\n            stream.write(b\"GET / HTTP/1.1\\r\\n\\r\\n\")\n            stream.read_until(b\"\\r\\n\\r\\n\", self.stop)\n            self.wait()\n            stream.read_bytes(11, self.stop)\n            data = self.wait()\n            self.assertEqual(data, b\"Hello world\")\n\n        # Now let the timeout trigger and close the connection.\n        data = self.wait()\n        self.assertEqual(data, \"closed\")\n\n\nclass BodyLimitsTest(AsyncHTTPTestCase):\n    def get_app(self):\n        class BufferedHandler(RequestHandler):\n            def put(self):\n                self.write(str(len(self.request.body)))\n\n        @stream_request_body\n        class StreamingHandler(RequestHandler):\n            def initialize(self):\n                self.bytes_read = 0\n\n            def prepare(self):\n                if 'expected_size' in self.request.arguments:\n                    self.request.connection.set_max_body_size(\n                        int(self.get_argument('expected_size')))\n                if 'body_timeout' in self.request.arguments:\n                    self.request.connection.set_body_timeout(\n                        float(self.get_argument('body_timeout')))\n\n            def data_received(self, data):\n                self.bytes_read += len(data)\n\n            def put(self):\n                self.write(str(self.bytes_read))\n\n        return Application([('/buffered', BufferedHandler),\n                            ('/streaming', StreamingHandler)])\n\n    def get_httpserver_options(self):\n        return dict(body_timeout=3600, max_body_size=4096)\n\n    def get_http_client(self):\n        # body_producer doesn't work on curl_httpclient, so override the\n        # configured AsyncHTTPClient implementation.\n        return SimpleAsyncHTTPClient(io_loop=self.io_loop)\n\n    def test_small_body(self):\n        response = self.fetch('/buffered', method='PUT', body=b'a' * 4096)\n        self.assertEqual(response.body, b'4096')\n        response = self.fetch('/streaming', method='PUT', body=b'a' * 4096)\n        self.assertEqual(response.body, b'4096')\n\n    def test_large_body_buffered(self):\n        with ExpectLog(gen_log, '.*Content-Length too long'):\n            response = self.fetch('/buffered', method='PUT', body=b'a' * 10240)\n        self.assertEqual(response.code, 599)\n\n    def test_large_body_buffered_chunked(self):\n        with ExpectLog(gen_log, '.*chunked body too large'):\n            response = self.fetch('/buffered', method='PUT',\n                                  body_producer=lambda write: write(b'a' * 10240))\n        self.assertEqual(response.code, 599)\n\n    def test_large_body_streaming(self):\n        with ExpectLog(gen_log, '.*Content-Length too long'):\n            response = self.fetch('/streaming', method='PUT', body=b'a' * 10240)\n        self.assertEqual(response.code, 599)\n\n    def test_large_body_streaming_chunked(self):\n        with ExpectLog(gen_log, '.*chunked body too large'):\n            response = self.fetch('/streaming', method='PUT',\n                                  body_producer=lambda write: write(b'a' * 10240))\n        self.assertEqual(response.code, 599)\n\n    def test_large_body_streaming_override(self):\n        response = self.fetch('/streaming?expected_size=10240', method='PUT',\n                              body=b'a' * 10240)\n        self.assertEqual(response.body, b'10240')\n\n    def test_large_body_streaming_chunked_override(self):\n        response = self.fetch('/streaming?expected_size=10240', method='PUT',\n                              body_producer=lambda write: write(b'a' * 10240))\n        self.assertEqual(response.body, b'10240')\n\n    @gen_test\n    def test_timeout(self):\n        stream = IOStream(socket.socket())\n        try:\n            yield stream.connect(('127.0.0.1', self.get_http_port()))\n            # Use a raw stream because AsyncHTTPClient won't let us read a\n            # response without finishing a body.\n            stream.write(b'PUT /streaming?body_timeout=0.1 HTTP/1.0\\r\\n'\n                         b'Content-Length: 42\\r\\n\\r\\n')\n            with ExpectLog(gen_log, 'Timeout reading body'):\n                response = yield stream.read_until_close()\n            self.assertEqual(response, b'')\n        finally:\n            stream.close()\n\n    @gen_test\n    def test_body_size_override_reset(self):\n        # The max_body_size override is reset between requests.\n        stream = IOStream(socket.socket())\n        try:\n            yield stream.connect(('127.0.0.1', self.get_http_port()))\n            # Use a raw stream so we can make sure it's all on one connection.\n            stream.write(b'PUT /streaming?expected_size=10240 HTTP/1.1\\r\\n'\n                         b'Content-Length: 10240\\r\\n\\r\\n')\n            stream.write(b'a' * 10240)\n            headers, response = yield gen.Task(read_stream_body, stream)\n            self.assertEqual(response, b'10240')\n            # Without the ?expected_size parameter, we get the old default value\n            stream.write(b'PUT /streaming HTTP/1.1\\r\\n'\n                         b'Content-Length: 10240\\r\\n\\r\\n')\n            with ExpectLog(gen_log, '.*Content-Length too long'):\n                data = yield stream.read_until_close()\n            self.assertEqual(data, b'')\n        finally:\n            stream.close()\n\n\nclass LegacyInterfaceTest(AsyncHTTPTestCase):\n    def get_app(self):\n        # The old request_callback interface does not implement the\n        # delegate interface, and writes its response via request.write\n        # instead of request.connection.write_headers.\n        def handle_request(request):\n            self.http1 = request.version.startswith(\"HTTP/1.\")\n            if not self.http1:\n                # This test will be skipped if we're using HTTP/2,\n                # so just close it out cleanly using the modern interface.\n                request.connection.write_headers(\n                    ResponseStartLine('', 200, 'OK'),\n                    HTTPHeaders())\n                request.connection.finish()\n                return\n            message = b\"Hello world\"\n            request.write(utf8(\"HTTP/1.1 200 OK\\r\\n\"\n                               \"Content-Length: %d\\r\\n\\r\\n\" % len(message)))\n            request.write(message)\n            request.finish()\n        return handle_request\n\n    def test_legacy_interface(self):\n        response = self.fetch('/')\n        if not self.http1:\n            self.skipTest(\"requires HTTP/1.x\")\n        self.assertEqual(response.body, b\"Hello world\")\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 727ms\nPrepared 1 package in 934ms\nInstalled 1 package in 0.76ms\n + tornado==4.5.dev1 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579)\nResolved 29 packages in 16ms\nInstalled 29 packages in 114ms\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579\n.......................................................................\ncollected 71 items\n\n=================================== ERRORS =====================================\n__________ BadSSLOptionsTest.test_missing_key __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 187, in test_missing_key\n    HTTPServer(application, ssl_options={\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/util.py\", line 270, in __new__\n    instance.initialize(*args, **init_kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/httpserver.py\", line 153, in initialize\n    TCPServer.__init__(self, io_loop=io_loop, ssl_options=ssl_options,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 111, in __init__\n    raise ValueError('certfile \"%s\" does not exist' %\nValueError: certfile \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test.crt\" does not exist\n__________ BodyLimitsTest.test_body_size_override_reset __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 527, in post_coroutine\n    return self.io_loop.run_sync(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/ioloop.py\", line 457, in run_sync\n    return future_cell[0].result()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/concurrent.py\", line 237, in result\n    raise_exc_info(self._exc_info)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/gen.py\", line 1024, in run\n    yielded = self.gen.send(value)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/types.py\", line 215, in send\n    return self.__wrapped.send(val)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 1092, in test_body_size_override_reset\n    data = yield stream.read_until_close()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ BodyLimitsTest.test_large_body_buffered __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 1031, in test_large_body_buffered\n    response = self.fetch('/buffered', method='PUT', body=b'a' * 10240)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ BodyLimitsTest.test_large_body_buffered_chunked __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 1036, in test_large_body_buffered_chunked\n    response = self.fetch('/buffered', method='PUT',\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ BodyLimitsTest.test_large_body_streaming __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 1042, in test_large_body_streaming\n    response = self.fetch('/streaming', method='PUT', body=b'a' * 10240)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ BodyLimitsTest.test_large_body_streaming_chunked __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 1047, in test_large_body_streaming_chunked\n    response = self.fetch('/streaming', method='PUT',\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ BodyLimitsTest.test_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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 527, in post_coroutine\n    return self.io_loop.run_sync(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/ioloop.py\", line 457, in run_sync\n    return future_cell[0].result()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/concurrent.py\", line 237, in result\n    raise_exc_info(self._exc_info)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/gen.py\", line 1024, in run\n    yielded = self.gen.send(value)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/types.py\", line 215, in send\n    return self.__wrapped.send(val)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 1071, in test_timeout\n    response = yield stream.read_until_close()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ HTTPServerRawTest.test_invalid_content_length __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 473, in test_invalid_content_length\n    self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ HTTPServerRawTest.test_malformed_first_line __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 416, in test_malformed_first_line\n    self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ HTTPServerRawTest.test_malformed_headers __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 423, in test_malformed_headers\n    self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ SSLContextTest.test_error_logging __________\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 588, in run\n    self._callSetUp()\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 547, in _callSetUp\n    self.setUp()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 381, in setUp\n    self.http_server = self.get_http_server()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 389, in get_http_server\n    **self.get_httpserver_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 449, in get_httpserver_options\n    return dict(ssl_options=self.get_ssl_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 155, in get_ssl_options\n    context = ssl_options_to_context(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLContextTest.test_large_post __________\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 588, in run\n    self._callSetUp()\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 547, in _callSetUp\n    self.setUp()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 381, in setUp\n    self.http_server = self.get_http_server()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 389, in get_http_server\n    **self.get_httpserver_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 449, in get_httpserver_options\n    return dict(ssl_options=self.get_ssl_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 155, in get_ssl_options\n    context = ssl_options_to_context(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLContextTest.test_non_ssl_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 588, in run\n    self._callSetUp()\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 547, in _callSetUp\n    self.setUp()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 381, in setUp\n    self.http_server = self.get_http_server()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 389, in get_http_server\n    **self.get_httpserver_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 449, in get_httpserver_options\n    return dict(ssl_options=self.get_ssl_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 155, in get_ssl_options\n    context = ssl_options_to_context(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLContextTest.test_ssl __________\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 588, in run\n    self._callSetUp()\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 547, in _callSetUp\n    self.setUp()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 381, in setUp\n    self.http_server = self.get_http_server()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 389, in get_http_server\n    **self.get_httpserver_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 449, in get_httpserver_options\n    return dict(ssl_options=self.get_ssl_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 155, in get_ssl_options\n    context = ssl_options_to_context(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLXHeaderTest.test_request_without_xprotocol __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 552, in test_request_without_xprotocol\n    self.assertEqual(self.fetch_json(\"/\")[\"remote_protocol\"], \"https\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 53, in fetch_json\n    response = self.fetch(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 406, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLv23Test.test_error_logging __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 125, in test_error_logging\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLv23Test.test_large_post __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 100, in test_large_post\n    response = self.fetch('/',\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 406, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLv23Test.test_non_ssl_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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 116, in test_non_ssl_request\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLv23Test.test_ssl __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 96, in test_ssl\n    response = self.fetch('/')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 406, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLv3Test.test_error_logging __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 125, in test_error_logging\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLv3Test.test_large_post __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 100, in test_large_post\n    response = self.fetch('/',\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 406, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLv3Test.test_non_ssl_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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 116, in test_non_ssl_request\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLv3Test.test_ssl __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 96, in test_ssl\n    response = self.fetch('/')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 406, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ TLSv1Test.test_error_logging __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 125, in test_error_logging\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ TLSv1Test.test_large_post __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 100, in test_large_post\n    response = self.fetch('/',\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 406, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ TLSv1Test.test_non_ssl_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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 116, in test_non_ssl_request\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ TLSv1Test.test_ssl __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 96, in test_ssl\n    response = self.fetch('/')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 406, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ UnixSocketTest.test_unix_socket_bad_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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 622, in test_unix_socket_bad_request\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n\n==================== short test summary info ====================\nPASSED r2e_tests.test_1::BadSSLOptionsTest::test_missing_arguments\nERROR r2e_tests.test_1::BadSSLOptionsTest::test_missing_key\nERROR r2e_tests.test_1::BodyLimitsTest::test_body_size_override_reset\nERROR r2e_tests.test_1::BodyLimitsTest::test_large_body_buffered\nERROR r2e_tests.test_1::BodyLimitsTest::test_large_body_buffered_chunked\nERROR r2e_tests.test_1::BodyLimitsTest::test_large_body_streaming\nERROR r2e_tests.test_1::BodyLimitsTest::test_large_body_streaming_chunked\nPASSED r2e_tests.test_1::BodyLimitsTest::test_large_body_streaming_chunked_override\nPASSED r2e_tests.test_1::BodyLimitsTest::test_large_body_streaming_override\nPASSED r2e_tests.test_1::BodyLimitsTest::test_small_body\nERROR r2e_tests.test_1::BodyLimitsTest::test_timeout\nPASSED r2e_tests.test_1::GzipTest::test_gzip\nPASSED r2e_tests.test_1::GzipTest::test_uncompressed\nPASSED r2e_tests.test_1::GzipUnsupportedTest::test_gzip_unsupported\nPASSED r2e_tests.test_1::GzipUnsupportedTest::test_uncompressed\nPASSED r2e_tests.test_1::HTTPConnectionTest::test_100_continue\nPASSED r2e_tests.test_1::HTTPConnectionTest::test_multipart_form\nPASSED r2e_tests.test_1::HTTPConnectionTest::test_newlines\nPASSED r2e_tests.test_1::HTTPServerRawTest::test_chunked_request_body\nPASSED r2e_tests.test_1::HTTPServerRawTest::test_chunked_request_uppercase\nPASSED r2e_tests.test_1::HTTPServerRawTest::test_empty_request\nERROR r2e_tests.test_1::HTTPServerRawTest::test_invalid_content_length\nERROR r2e_tests.test_1::HTTPServerRawTest::test_malformed_first_line\nERROR r2e_tests.test_1::HTTPServerRawTest::test_malformed_headers\nPASSED r2e_tests.test_1::HTTPServerTest::test_double_slash\nPASSED r2e_tests.test_1::HTTPServerTest::test_empty_post_parameters\nPASSED r2e_tests.test_1::HTTPServerTest::test_empty_query_string\nPASSED r2e_tests.test_1::HTTPServerTest::test_malformed_body\nPASSED r2e_tests.test_1::HTTPServerTest::test_query_string_encoding\nPASSED r2e_tests.test_1::HTTPServerTest::test_types\nPASSED r2e_tests.test_1::IdleTimeoutTest::test_idle_after_use\nPASSED r2e_tests.test_1::IdleTimeoutTest::test_unused_connection\nPASSED r2e_tests.test_1::KeepAliveTest::test_cancel_during_download\nPASSED r2e_tests.test_1::KeepAliveTest::test_finish_while_closed\nPASSED r2e_tests.test_1::KeepAliveTest::test_http10\nPASSED r2e_tests.test_1::KeepAliveTest::test_http10_keepalive\nPASSED r2e_tests.test_1::KeepAliveTest::test_http10_keepalive_extra_crlf\nPASSED r2e_tests.test_1::KeepAliveTest::test_keepalive_chunked\nPASSED r2e_tests.test_1::KeepAliveTest::test_pipelined_cancel\nPASSED r2e_tests.test_1::KeepAliveTest::test_pipelined_requests\nPASSED r2e_tests.test_1::KeepAliveTest::test_request_close\nPASSED r2e_tests.test_1::KeepAliveTest::test_two_requests\nPASSED r2e_tests.test_1::LegacyInterfaceTest::test_legacy_interface\nPASSED r2e_tests.test_1::ManualProtocolTest::test_manual_protocol\nPASSED r2e_tests.test_1::MaxHeaderSizeTest::test_large_headers\nPASSED r2e_tests.test_1::MaxHeaderSizeTest::test_small_headers\nERROR r2e_tests.test_1::SSLContextTest::test_error_logging\nERROR r2e_tests.test_1::SSLContextTest::test_large_post\nERROR r2e_tests.test_1::SSLContextTest::test_non_ssl_request\nERROR r2e_tests.test_1::SSLContextTest::test_ssl\nERROR r2e_tests.test_1::SSLXHeaderTest::test_request_without_xprotocol\nERROR r2e_tests.test_1::SSLv23Test::test_error_logging\nERROR r2e_tests.test_1::SSLv23Test::test_large_post\nERROR r2e_tests.test_1::SSLv23Test::test_non_ssl_request\nERROR r2e_tests.test_1::SSLv23Test::test_ssl\nERROR r2e_tests.test_1::SSLv3Test::test_error_logging\nERROR r2e_tests.test_1::SSLv3Test::test_large_post\nERROR r2e_tests.test_1::SSLv3Test::test_non_ssl_request\nERROR r2e_tests.test_1::SSLv3Test::test_ssl\nPASSED r2e_tests.test_1::StreamingChunkSizeTest::test_chunked_body\nPASSED r2e_tests.test_1::StreamingChunkSizeTest::test_chunked_compressed\nPASSED r2e_tests.test_1::StreamingChunkSizeTest::test_compressed_body\nPASSED r2e_tests.test_1::StreamingChunkSizeTest::test_regular_body\nERROR r2e_tests.test_1::TLSv1Test::test_error_logging\nERROR r2e_tests.test_1::TLSv1Test::test_large_post\nERROR r2e_tests.test_1::TLSv1Test::test_non_ssl_request\nERROR r2e_tests.test_1::TLSv1Test::test_ssl\nPASSED r2e_tests.test_1::UnixSocketTest::test_unix_socket\nERROR r2e_tests.test_1::UnixSocketTest::test_unix_socket_bad_request\nPASSED r2e_tests.test_1::XHeaderTest::test_ip_headers\nPASSED r2e_tests.test_1::XHeaderTest::test_scheme_headers\n=================== 28 errors, 43 passed in 0.52s ===================\n",
    "new_commit_res_stderr": "",
    "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_613299c6d4f705e3145847ebc88b3dd6f9bb3579\n.......................................................................\ncollected 71 items\n\n=================================== FAILURES ===================================\n__________ HTTPServerRawTest.test_chunked_request_uppercase __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 461, in test_chunked_request_uppercase\n    self.assertEqual(json_decode(response), {u'foo': [u'bar']})\nAssertionError: {} != {'foo': ['bar']}\n- {}\n+ {'foo': ['bar']}\n\n=================================== ERRORS =====================================\n__________ BadSSLOptionsTest.test_missing_key __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 187, in test_missing_key\n    HTTPServer(application, ssl_options={\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/util.py\", line 270, in __new__\n    instance.initialize(*args, **init_kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/httpserver.py\", line 153, in initialize\n    TCPServer.__init__(self, io_loop=io_loop, ssl_options=ssl_options,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 111, in __init__\n    raise ValueError('certfile \"%s\" does not exist' %\nValueError: certfile \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test.crt\" does not exist\n__________ BodyLimitsTest.test_body_size_override_reset __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 527, in post_coroutine\n    return self.io_loop.run_sync(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/ioloop.py\", line 457, in run_sync\n    return future_cell[0].result()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/concurrent.py\", line 237, in result\n    raise_exc_info(self._exc_info)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/gen.py\", line 1024, in run\n    yielded = self.gen.send(value)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/types.py\", line 215, in send\n    return self.__wrapped.send(val)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 1092, in test_body_size_override_reset\n    data = yield stream.read_until_close()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ BodyLimitsTest.test_large_body_buffered __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 1031, in test_large_body_buffered\n    response = self.fetch('/buffered', method='PUT', body=b'a' * 10240)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ BodyLimitsTest.test_large_body_buffered_chunked __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 1036, in test_large_body_buffered_chunked\n    response = self.fetch('/buffered', method='PUT',\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ BodyLimitsTest.test_large_body_streaming __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 1042, in test_large_body_streaming\n    response = self.fetch('/streaming', method='PUT', body=b'a' * 10240)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ BodyLimitsTest.test_large_body_streaming_chunked __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 1047, in test_large_body_streaming_chunked\n    response = self.fetch('/streaming', method='PUT',\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ BodyLimitsTest.test_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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 527, in post_coroutine\n    return self.io_loop.run_sync(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/ioloop.py\", line 457, in run_sync\n    return future_cell[0].result()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/concurrent.py\", line 237, in result\n    raise_exc_info(self._exc_info)\n  File \"<string>\", line 3, in raise_exc_info\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/gen.py\", line 1024, in run\n    yielded = self.gen.send(value)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/types.py\", line 215, in send\n    return self.__wrapped.send(val)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 1071, in test_timeout\n    response = yield stream.read_until_close()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ HTTPServerRawTest.test_invalid_content_length __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 473, in test_invalid_content_length\n    self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ HTTPServerRawTest.test_malformed_first_line __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 416, in test_malformed_first_line\n    self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ HTTPServerRawTest.test_malformed_headers __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 423, in test_malformed_headers\n    self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n__________ SSLContextTest.test_error_logging __________\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 588, in run\n    self._callSetUp()\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 547, in _callSetUp\n    self.setUp()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 381, in setUp\n    self.http_server = self.get_http_server()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 389, in get_http_server\n    **self.get_httpserver_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 449, in get_httpserver_options\n    return dict(ssl_options=self.get_ssl_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 155, in get_ssl_options\n    context = ssl_options_to_context(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLContextTest.test_large_post __________\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 588, in run\n    self._callSetUp()\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 547, in _callSetUp\n    self.setUp()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 381, in setUp\n    self.http_server = self.get_http_server()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 389, in get_http_server\n    **self.get_httpserver_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 449, in get_httpserver_options\n    return dict(ssl_options=self.get_ssl_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 155, in get_ssl_options\n    context = ssl_options_to_context(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLContextTest.test_non_ssl_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 588, in run\n    self._callSetUp()\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 547, in _callSetUp\n    self.setUp()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 381, in setUp\n    self.http_server = self.get_http_server()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 389, in get_http_server\n    **self.get_httpserver_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 449, in get_httpserver_options\n    return dict(ssl_options=self.get_ssl_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 155, in get_ssl_options\n    context = ssl_options_to_context(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLContextTest.test_ssl __________\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 588, in run\n    self._callSetUp()\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 547, in _callSetUp\n    self.setUp()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 381, in setUp\n    self.http_server = self.get_http_server()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 389, in get_http_server\n    **self.get_httpserver_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 449, in get_httpserver_options\n    return dict(ssl_options=self.get_ssl_options())\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 155, in get_ssl_options\n    context = ssl_options_to_context(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLXHeaderTest.test_request_without_xprotocol __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 552, in test_request_without_xprotocol\n    self.assertEqual(self.fetch_json(\"/\")[\"remote_protocol\"], \"https\")\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 53, in fetch_json\n    response = self.fetch(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 406, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLv23Test.test_error_logging __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 125, in test_error_logging\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLv23Test.test_large_post __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 100, in test_large_post\n    response = self.fetch('/',\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 406, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLv23Test.test_non_ssl_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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 116, in test_non_ssl_request\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLv23Test.test_ssl __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 96, in test_ssl\n    response = self.fetch('/')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 406, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLv3Test.test_error_logging __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 125, in test_error_logging\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLv3Test.test_large_post __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 100, in test_large_post\n    response = self.fetch('/',\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 406, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLv3Test.test_non_ssl_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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 116, in test_non_ssl_request\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ SSLv3Test.test_ssl __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 96, in test_ssl\n    response = self.fetch('/')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 406, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ TLSv1Test.test_error_logging __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 125, in test_error_logging\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ TLSv1Test.test_large_post __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 100, in test_large_post\n    response = self.fetch('/',\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 406, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ TLSv1Test.test_non_ssl_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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 116, in test_non_ssl_request\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ TLSv1Test.test_ssl __________\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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 96, in test_ssl\n    response = self.fetch('/')\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 406, in fetch\n    return self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 336, in wait\n    self.__rethrow()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 272, 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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/stack_context.py\", line 314, in wrapped\n    ret = fn(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 272, in accept_handler\n    callback(connection, address)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/tcpserver.py\", line 241, in _handle_connection\n    connection = ssl_wrap_socket(connection,\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 513, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/netutil.py\", line 490, 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__________ UnixSocketTest.test_unix_socket_bad_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_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 136, in __call__\n    result = self.orig_method(*args, **kwargs)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/r2e_tests/test_1.py\", line 622, in test_unix_socket_bad_request\n    response = self.wait()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_613299c6d4f705e3145847ebc88b3dd6f9bb3579/tornado/testing.py\", line 651, in __exit__\n    raise Exception(\"did not get expected log message\")\nException: did not get expected log message\n\n==================== short test summary info ====================\nPASSED r2e_tests.test_1::BadSSLOptionsTest::test_missing_arguments\nERROR r2e_tests.test_1::BadSSLOptionsTest::test_missing_key\nERROR r2e_tests.test_1::BodyLimitsTest::test_body_size_override_reset\nERROR r2e_tests.test_1::BodyLimitsTest::test_large_body_buffered\nERROR r2e_tests.test_1::BodyLimitsTest::test_large_body_buffered_chunked\nERROR r2e_tests.test_1::BodyLimitsTest::test_large_body_streaming\nERROR r2e_tests.test_1::BodyLimitsTest::test_large_body_streaming_chunked\nPASSED r2e_tests.test_1::BodyLimitsTest::test_large_body_streaming_chunked_override\nPASSED r2e_tests.test_1::BodyLimitsTest::test_large_body_streaming_override\nPASSED r2e_tests.test_1::BodyLimitsTest::test_small_body\nERROR r2e_tests.test_1::BodyLimitsTest::test_timeout\nPASSED r2e_tests.test_1::GzipTest::test_gzip\nPASSED r2e_tests.test_1::GzipTest::test_uncompressed\nPASSED r2e_tests.test_1::GzipUnsupportedTest::test_gzip_unsupported\nPASSED r2e_tests.test_1::GzipUnsupportedTest::test_uncompressed\nPASSED r2e_tests.test_1::HTTPConnectionTest::test_100_continue\nPASSED r2e_tests.test_1::HTTPConnectionTest::test_multipart_form\nPASSED r2e_tests.test_1::HTTPConnectionTest::test_newlines\nPASSED r2e_tests.test_1::HTTPServerRawTest::test_chunked_request_body\nFAILED r2e_tests.test_1::HTTPServerRawTest::test_chunked_request_uppercase\nPASSED r2e_tests.test_1::HTTPServerRawTest::test_empty_request\nERROR r2e_tests.test_1::HTTPServerRawTest::test_invalid_content_length\nERROR r2e_tests.test_1::HTTPServerRawTest::test_malformed_first_line\nERROR r2e_tests.test_1::HTTPServerRawTest::test_malformed_headers\nPASSED r2e_tests.test_1::HTTPServerTest::test_double_slash\nPASSED r2e_tests.test_1::HTTPServerTest::test_empty_post_parameters\nPASSED r2e_tests.test_1::HTTPServerTest::test_empty_query_string\nPASSED r2e_tests.test_1::HTTPServerTest::test_malformed_body\nPASSED r2e_tests.test_1::HTTPServerTest::test_query_string_encoding\nPASSED r2e_tests.test_1::HTTPServerTest::test_types\nPASSED r2e_tests.test_1::IdleTimeoutTest::test_idle_after_use\nPASSED r2e_tests.test_1::IdleTimeoutTest::test_unused_connection\nPASSED r2e_tests.test_1::KeepAliveTest::test_cancel_during_download\nPASSED r2e_tests.test_1::KeepAliveTest::test_finish_while_closed\nPASSED r2e_tests.test_1::KeepAliveTest::test_http10\nPASSED r2e_tests.test_1::KeepAliveTest::test_http10_keepalive\nPASSED r2e_tests.test_1::KeepAliveTest::test_http10_keepalive_extra_crlf\nPASSED r2e_tests.test_1::KeepAliveTest::test_keepalive_chunked\nPASSED r2e_tests.test_1::KeepAliveTest::test_pipelined_cancel\nPASSED r2e_tests.test_1::KeepAliveTest::test_pipelined_requests\nPASSED r2e_tests.test_1::KeepAliveTest::test_request_close\nPASSED r2e_tests.test_1::KeepAliveTest::test_two_requests\nPASSED r2e_tests.test_1::LegacyInterfaceTest::test_legacy_interface\nPASSED r2e_tests.test_1::ManualProtocolTest::test_manual_protocol\nPASSED r2e_tests.test_1::MaxHeaderSizeTest::test_large_headers\nPASSED r2e_tests.test_1::MaxHeaderSizeTest::test_small_headers\nERROR r2e_tests.test_1::SSLContextTest::test_error_logging\nERROR r2e_tests.test_1::SSLContextTest::test_large_post\nERROR r2e_tests.test_1::SSLContextTest::test_non_ssl_request\nERROR r2e_tests.test_1::SSLContextTest::test_ssl\nERROR r2e_tests.test_1::SSLXHeaderTest::test_request_without_xprotocol\nERROR r2e_tests.test_1::SSLv23Test::test_error_logging\nERROR r2e_tests.test_1::SSLv23Test::test_large_post\nERROR r2e_tests.test_1::SSLv23Test::test_non_ssl_request\nERROR r2e_tests.test_1::SSLv23Test::test_ssl\nERROR r2e_tests.test_1::SSLv3Test::test_error_logging\nERROR r2e_tests.test_1::SSLv3Test::test_large_post\nERROR r2e_tests.test_1::SSLv3Test::test_non_ssl_request\nERROR r2e_tests.test_1::SSLv3Test::test_ssl\nPASSED r2e_tests.test_1::StreamingChunkSizeTest::test_chunked_body\nPASSED r2e_tests.test_1::StreamingChunkSizeTest::test_chunked_compressed\nPASSED r2e_tests.test_1::StreamingChunkSizeTest::test_compressed_body\nPASSED r2e_tests.test_1::StreamingChunkSizeTest::test_regular_body\nERROR r2e_tests.test_1::TLSv1Test::test_error_logging\nERROR r2e_tests.test_1::TLSv1Test::test_large_post\nERROR r2e_tests.test_1::TLSv1Test::test_non_ssl_request\nERROR r2e_tests.test_1::TLSv1Test::test_ssl\nPASSED r2e_tests.test_1::UnixSocketTest::test_unix_socket\nERROR r2e_tests.test_1::UnixSocketTest::test_unix_socket_bad_request\nPASSED r2e_tests.test_1::XHeaderTest::test_ip_headers\nPASSED r2e_tests.test_1::XHeaderTest::test_scheme_headers\n=================== 1 failed, 28 errors, 42 passed in 0.45s ===================\n",
    "old_commit_res_stderr": ""
}
tornado/http1connection.py tornado/test/httpserver_test.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** Transfer-Encoding Header with Uppercase Value Not Recognized as Chunked

**Description:**
When sending an HTTP request with the `Transfer-Encoding` header value set to `"Chunked"` using uppercase letters, the server fails to recognize it as chunked encoding. As a result, the request body is not properly parsed, leading to an empty response instead of the expected data.

**Example Code:**
```python
self.stream.write(b"""\
POST /echo HTTP/1.1
Transfer-Encoding: Chunked
Content-Type: application/x-www-form-urlencoded

4
foo=
3
bar
0

""".replace(b"\n", b"\r\n"))
read_stream_body(self.stream, self.stop)
headers, response = self.wait()
self.assertEqual(json_decode(response), {u'foo': [u'bar']})
```

**Expected Behavior:**
The server should correctly interpret the `Transfer-Encoding` header value `"Chunked"` (case-insensitive) and parse the request body accordingly, resulting in a JSON response:
```json
{
  "foo": ["bar"]
}
```

**Actual Behavior:**
The server does not recognize the uppercase `"Chunked"` value for the `Transfer-Encoding` header, leading to an empty JSON response:
```json
{}
```
[/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/http1connection.py
#!/usr/bin/env python
#
# Copyright 2014 Facebook
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

"""Client and server implementations of HTTP/1.x.

.. versionadded:: 4.0
"""

from __future__ import absolute_import, division, print_function, with_statement

import re

from tornado.concurrent import Future
from tornado.escape import native_str, utf8
from tornado import gen
from tornado import httputil
from tornado import iostream
from tornado.log import gen_log, app_log
from tornado import stack_context
from tornado.util import GzipDecompressor, PY3


class _QuietException(Exception):
    def __init__(self):
        pass


class _ExceptionLoggingContext(object):
    """Used with the ``with`` statement when calling delegate methods to
    log any exceptions with the given logger.  Any exceptions caught are
    converted to _QuietException
    """
    def __init__(self, logger):
        self.logger = logger

    def __enter__(self):
        pass

    def __exit__(self, typ, value, tb):
        if value is not None:
            self.logger.error("Uncaught exception", exc_info=(typ, value, tb))
            raise _QuietException


class HTTP1ConnectionParameters(object):
    """Parameters for `.HTTP1Connection` and `.HTTP1ServerConnection`.
    """
    def __init__(self, no_keep_alive=False, chunk_size=None,
                 max_header_size=None, header_timeout=None, max_body_size=None,
                 body_timeout=None, decompress=False):
        """
        :arg bool no_keep_alive: If true, always close the connection after
            one request.
        :arg int chunk_size: how much data to read into memory at once
        :arg int max_header_size:  maximum amount of data for HTTP headers
        :arg float header_timeout: how long to wait for all headers (seconds)
        :arg int max_body_size: maximum amount of data for body
        :arg float body_timeout: how long to wait while reading body (seconds)
        :arg bool decompress: if true, decode incoming
            ``Content-Encoding: gzip``
        """
        self.no_keep_alive = no_keep_alive
        self.chunk_size = chunk_size or 65536
        self.max_header_size = max_header_size or 65536
        self.header_timeout = header_timeout
        self.max_body_size = max_body_size
        self.body_timeout = body_timeout
        self.decompress = decompress


class HTTP1Connection(httputil.HTTPConnection):
    """Implements the HTTP/1.x protocol.

    This class can be on its own for clients, or via `HTTP1ServerConnection`
    for servers.
    """
    def __init__(self, stream, is_client, params=None, context=None):
        """
        :arg stream: an `.IOStream`
        :arg bool is_client: client or server
        :arg params: a `.HTTP1ConnectionParameters` instance or ``None``
        :arg context: an opaque application-defined object that can be accessed
            as ``connection.context``.
        """
        self.is_client = is_client
        self.stream = stream
        if params is None:
            params = HTTP1ConnectionParameters()
        self.params = params
        self.context = context
        self.no_keep_alive = params.no_keep_alive
        # The body limits can be altered by the delegate, so save them
        # here instead of just referencing self.params later.
        self._max_body_size = (self.params.max_body_size or
                               self.stream.max_buffer_size)
        self._body_timeout = self.params.body_timeout
        # _write_finished is set to True when finish() has been called,
        # i.e. there will be no more data sent.  Data may still be in the
        # stream's write buffer.
        self._write_finished = False
        # True when we have read the entire incoming body.
        self._read_finished = False
        # _finish_future resolves when all data has been written and flushed
        # to the IOStream.
        self._finish_future = Future()
        # If true, the connection should be closed after this request
        # (after the response has been written in the server side,
        # and after it has been read in the client)
        self._disconnect_on_finish = False
        self._clear_callbacks()
        # Save the start lines after we read or write them; they
        # affect later processing (e.g. 304 responses and HEAD methods
        # have content-length but no bodies)
        self._request_start_line = None
        self._response_start_line = None
        self._request_headers = None
        # True if we are writing output with chunked encoding.
        self._chunking_output = None
        # While reading a body with a content-length, this is the
        # amount left to read.
        self._expected_content_remaining = None
        # A Future for our outgoing writes, returned by IOStream.write.
        self._pending_write = None

    def read_response(self, delegate):
        """Read a single HTTP response.

        Typical client-mode usage is to write a request using `write_headers`,
        `write`, and `finish`, and then call ``read_response``.

        :arg delegate: a `.HTTPMessageDelegate`

        Returns a `.Future` that resolves to None after the full response has
        been read.
        """
        if self.params.decompress:
            delegate = _GzipMessageDelegate(delegate, self.params.chunk_size)
        return self._read_message(delegate)

    @gen.coroutine
    def _read_message(self, delegate):
        need_delegate_close = False
        try:
            header_future = self.stream.read_until_regex(
                b"\r?\n\r?\n",
                max_bytes=self.params.max_header_size)
            if self.params.header_timeout is None:
                header_data = yield header_future
            else:
                try:
                    header_data = yield gen.with_timeout(
                        self.stream.io_loop.time() + self.params.header_timeout,
                        header_future,
                        io_loop=self.stream.io_loop,
                        quiet_exceptions=iostream.StreamClosedError)
                except gen.TimeoutError:
                    self.close()
                    raise gen.Return(False)
            start_line, headers = self._parse_headers(header_data)
            if self.is_client:
                start_line = httputil.parse_response_start_line(start_line)
                self._response_start_line = start_line
            else:
                start_line = httputil.parse_request_start_line(start_line)
                self._request_start_line = start_line
                self._request_headers = headers

            self._disconnect_on_finish = not self._can_keep_alive(
                start_line, headers)
            need_delegate_close = True
            with _ExceptionLoggingContext(app_log):
                header_future = delegate.headers_received(start_line, headers)
                if header_future is not None:
                    yield header_future
            if self.stream is None:
                # We've been detached.
                need_delegate_close = False
                raise gen.Return(False)
            skip_body = False
            if self.is_client:
                if (self._request_start_line is not None and
                        self._request_start_line.method == 'HEAD'):
                    skip_body = True
                code = start_line.code
                if code == 304:
                    # 304 responses may include the content-length header
                    # but do not actually have a body.
                    # http://tools.ietf.org/html/rfc7230#section-3.3
                    skip_body = True
                if code >= 100 and code < 200:
                    # 1xx responses should never indicate the presence of
                    # a body.
                    if ('Content-Length' in headers or
                            'Transfer-Encoding' in headers):
                        raise httputil.HTTPInputError(
                            "Response code %d cannot have body" % code)
                    # TODO: client delegates will get headers_received twice
                    # in the case of a 100-continue.  Document or change?
                    yield self._read_message(delegate)
            else:
                if (headers.get("Expect") == "100-continue" and
                        not self._write_finished):
                    self.stream.write(b"HTTP/1.1 100 (Continue)\r\n\r\n")
            if not skip_body:
                body_future = self._read_body(
                    start_line.code if self.is_client else 0, headers, delegate)
                if body_future is not None:
                    if self._body_timeout is None:
                        yield body_future
                    else:
                        try:
                            yield gen.with_timeout(
                                self.stream.io_loop.time() + self._body_timeout,
                                body_future, self.stream.io_loop,
                                quiet_exceptions=iostream.StreamClosedError)
                        except gen.TimeoutError:
                            gen_log.info("Timeout reading body from %s",
                                         self.context)
                            self.stream.close()
                            raise gen.Return(False)
            self._read_finished = True
            if not self._write_finished or self.is_client:
                need_delegate_close = False
                with _ExceptionLoggingContext(app_log):
                    delegate.finish()
            # If we're waiting for the application to produce an asynchronous
            # response, and we're not detached, register a close callback
            # on the stream (we didn't need one while we were reading)
            if (not self._finish_future.done() and
                    self.stream is not None and
                    not self.stream.closed()):
                self.stream.set_close_callback(self._on_connection_close)
                yield self._finish_future
            if self.is_client and self._disconnect_on_finish:
                self.close()
            if self.stream is None:
                raise gen.Return(False)
        except httputil.HTTPInputError as e:
            gen_log.info("Malformed HTTP message from %s: %s",
                         self.context, e)
            self.close()
            raise gen.Return(False)
        finally:
            if need_delegate_close:
                with _ExceptionLoggingContext(app_log):
                    delegate.on_connection_close()
            self._clear_callbacks()
        raise gen.Return(True)

    def _clear_callbacks(self):
        """Clears the callback attributes.

        This allows the request handler to be garbage collected more
        quickly in CPython by breaking up reference cycles.
        """
        self._write_callback = None
        self._write_future = None
        self._close_callback = None
        if self.stream is not None:
            self.stream.set_close_callback(None)

    def set_close_callback(self, callback):
        """Sets a callback that will be run when the connection is closed.

        .. deprecated:: 4.0
            Use `.HTTPMessageDelegate.on_connection_close` instead.
        """
        self._close_callback = stack_context.wrap(callback)

    def _on_connection_close(self):
        # Note that this callback is only registered on the IOStream
        # when we have finished reading the request and are waiting for
        # the application to produce its response.
        if self._close_callback is not None:
            callback = self._close_callback
            self._close_callback = None
            callback()
        if not self._finish_future.done():
            self._finish_future.set_result(None)
        self._clear_callbacks()

    def close(self):
        if self.stream is not None:
            self.stream.close()
        self._clear_callbacks()
        if not self._finish_future.done():
            self._finish_future.set_result(None)

    def detach(self):
        """Take control of the underlying stream.

        Returns the underlying `.IOStream` object and stops all further
        HTTP processing.  May only be called during
        `.HTTPMessageDelegate.headers_received`.  Intended for implementing
        protocols like websockets that tunnel over an HTTP handshake.
        """
        self._clear_callbacks()
        stream = self.stream
        self.stream = None
        if not self._finish_future.done():
            self._finish_future.set_result(None)
        return stream

    def set_body_timeout(self, timeout):
        """Sets the body timeout for a single request.

        Overrides the value from `.HTTP1ConnectionParameters`.
        """
        self._body_timeout = timeout

    def set_max_body_size(self, max_body_size):
        """Sets the body size limit for a single request.

        Overrides the value from `.HTTP1ConnectionParameters`.
        """
        self._max_body_size = max_body_size

    def write_headers(self, start_line, headers, chunk=None, callback=None):
        """Implements `.HTTPConnection.write_headers`."""
        lines = []
        if self.is_client:
            self._request_start_line = start_line
            lines.append(utf8('%s %s HTTP/1.1' % (start_line[0], start_line[1])))
            # Client requests with a non-empty body must have either a
            # Content-Length or a Transfer-Encoding.
            self._chunking_output = (
                start_line.method in ('POST', 'PUT', 'PATCH') and
                'Content-Length' not in headers and
                'Transfer-Encoding' not in headers)
        else:
            self._response_start_line = start_line
            lines.append(utf8('HTTP/1.1 %d %s' % (start_line[1], start_line[2])))
            self._chunking_output = (
                # TODO: should this use
                # self._request_start_line.version or
                # start_line.version?
                self._request_start_line.version == 'HTTP/1.1' and
                # 304 responses have no body (not even a zero-length body), and so
                # should not have either Content-Length or Transfer-Encoding.
                # headers.
                start_line.code not in (204, 304) and
                # No need to chunk the output if a Content-Length is specified.
                'Content-Length' not in headers and
                # Applications are discouraged from touching Transfer-Encoding,
                # but if they do, leave it alone.
                'Transfer-Encoding' not in headers)
            # If a 1.0 client asked for keep-alive, add the header.
            if (self._request_start_line.version == 'HTTP/1.0' and
                (self._request_headers.get('Connection', '').lower() ==
                 'keep-alive')):
                headers['Connection'] = 'Keep-Alive'
        if self._chunking_output:
            headers['Transfer-Encoding'] = 'chunked'
        if (not self.is_client and
            (self._request_start_line.method == 'HEAD' or
             start_line.code == 304)):
            self._expected_content_remaining = 0
        elif 'Content-Length' in headers:
            self._expected_content_remaining = int(headers['Content-Length'])
        else:
            self._expected_content_remaining = None
        # TODO: headers are supposed to be of type str, but we still have some
        # cases that let bytes slip through. Remove these native_str calls when those
        # are fixed.
        header_lines = (native_str(n) + ": " + native_str(v) for n, v in headers.get_all())
        if PY3:
            lines.extend(l.encode('latin1') for l in header_lines)
        else:
            lines.extend(header_lines)
        for line in lines:
            if b'\n' in line:
                raise ValueError('Newline in header: ' + repr(line))
        future = None
        if self.stream.closed():
            future = self._write_future = Future()
            future.set_exception(iostream.StreamClosedError())
            future.exception()
        else:
            if callback is not None:
                self._write_callback = stack_context.wrap(callback)
            else:
                future = self._write_future = Future()
            data = b"\r\n".join(lines) + b"\r\n\r\n"
            if chunk:
                data += self._format_chunk(chunk)
            self._pending_write = self.stream.write(data)
            self._pending_write.add_done_callback(self._on_write_complete)
        return future

    def _format_chunk(self, chunk):
        if self._expected_content_remaining is not None:
            self._expected_content_remaining -= len(chunk)
            if self._expected_content_remaining < 0:
                # Close the stream now to stop further framing errors.
                self.stream.close()
                raise httputil.HTTPOutputError(
                    "Tried to write more data than Content-Length")
        if self._chunking_output and chunk:
            # Don't write out empty chunks because that means END-OF-STREAM
            # with chunked encoding
            return utf8("%x" % len(chunk)) + b"\r\n" + chunk + b"\r\n"
        else:
            return chunk

    def write(self, chunk, callback=None):
        """Implements `.HTTPConnection.write`.

        For backwards compatibility is is allowed but deprecated to
        skip `write_headers` and instead call `write()` with a
        pre-encoded header block.
        """
        future = None
        if self.stream.closed():
            future = self._write_future = Future()
            self._write_future.set_exception(iostream.StreamClosedError())
            self._write_future.exception()
        else:
            if callback is not None:
                self._write_callback = stack_context.wrap(callback)
            else:
                future = self._write_future = Future()
            self._pending_write = self.stream.write(self._format_chunk(chunk))
            self._pending_write.add_done_callback(self._on_write_complete)
        return future

    def finish(self):
        """Implements `.HTTPConnection.finish`."""
        if (self._expected_content_remaining is not None and
                self._expected_content_remaining != 0 and
                not self.stream.closed()):
            self.stream.close()
            raise httputil.HTTPOutputError(
                "Tried to write %d bytes less than Content-Length" %
                self._expected_content_remaining)
        if self._chunking_output:
            if not self.stream.closed():
                self._pending_write = self.stream.write(b"0\r\n\r\n")
                self._pending_write.add_done_callback(self._on_write_complete)
        self._write_finished = True
        # If the app finished the request while we're still reading,
        # divert any remaining data away from the delegate and
        # close the connection when we're done sending our response.
        # Closing the connection is the only way to avoid reading the
        # whole input body.
        if not self._read_finished:
            self._disconnect_on_finish = True
        # No more data is coming, so instruct TCP to send any remaining
        # data immediately instead of waiting for a full packet or ack.
        self.stream.set_nodelay(True)
        if self._pending_write is None:
            self._finish_request(None)
        else:
            self._pending_write.add_done_callback(self._finish_request)

    def _on_write_complete(self, future):
        exc = future.exception()
        if exc is not None and not isinstance(exc, iostream.StreamClosedError):
            future.result()
        if self._write_callback is not None:
            callback = self._write_callback
            self._write_callback = None
            self.stream.io_loop.add_callback(callback)
        if self._write_future is not None:
            future = self._write_future
            self._write_future = None
            future.set_result(None)

    def _can_keep_alive(self, start_line, headers):
        if self.params.no_keep_alive:
            return False
        connection_header = headers.get("Connection")
        if connection_header is not None:
            connection_header = connection_header.lower()
        if start_line.version == "HTTP/1.1":
            return connection_header != "close"
        elif ("Content-Length" in headers or
              headers.get("Transfer-Encoding", "").lower() == "chunked" or
              getattr(start_line, 'method', None) in ("HEAD", "GET")):
            # start_line may be a request or reponse start line; only
            # the former has a method attribute.
            return connection_header == "keep-alive"
        return False

    def _finish_request(self, future):
        self._clear_callbacks()
        if not self.is_client and self._disconnect_on_finish:
            self.close()
            return
        # Turn Nagle's algorithm back on, leaving the stream in its
        # default state for the next request.
        self.stream.set_nodelay(False)
        if not self._finish_future.done():
            self._finish_future.set_result(None)

    def _parse_headers(self, data):
        # The lstrip removes newlines that some implementations sometimes
        # insert between messages of a reused connection.  Per RFC 7230,
        # we SHOULD ignore at least one empty line before the request.
        # http://tools.ietf.org/html/rfc7230#section-3.5
        data = native_str(data.decode('latin1')).lstrip("\r\n")
        # RFC 7230 section allows for both CRLF and bare LF.
        eol = data.find("\n")
        start_line = data[:eol].rstrip("\r")
        try:
            headers = httputil.HTTPHeaders.parse(data[eol:])
        except ValueError:
            # probably form split() if there was no ':' in the line
            raise httputil.HTTPInputError("Malformed HTTP headers: %r" %
                                          data[eol:100])
        return start_line, headers

    def _read_body(self, code, headers, delegate):
        if "Content-Length" in headers:
            if "Transfer-Encoding" in headers:
                # Response cannot contain both Content-Length and
                # Transfer-Encoding headers.
                # http://tools.ietf.org/html/rfc7230#section-3.3.3
                raise httputil.HTTPInputError(
                    "Response with both Transfer-Encoding and Content-Length")
            if "," in 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*', headers["Content-Length"])
                if any(i != pieces[0] for i in pieces):
                    raise httputil.HTTPInputError(
                        "Multiple unequal Content-Lengths: %r" %
                        headers["Content-Length"])
                headers["Content-Length"] = pieces[0]

            try:
                content_length = int(headers["Content-Length"])
            except ValueError:
                # Handles non-integer Content-Length value.
                raise httputil.HTTPInputError(
                    "Only integer Content-Length is allowed: %s" % headers["Content-Length"])

            if content_length > self._max_body_size:
                raise httputil.HTTPInputError("Content-Length too long")
        else:
            content_length = None

        if code == 204:
            # This response code is not allowed to have a non-empty body,
            # and has an implicit length of zero instead of read-until-close.
            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3
            if ("Transfer-Encoding" in headers or
                    content_length not in (None, 0)):
                raise httputil.HTTPInputError(
                    "Response with code %d should not have body" % code)
            content_length = 0

        if content_length is not None:
            return self._read_fixed_body(content_length, delegate)
        if headers.get("Transfer-Encoding") == "chunked":
            return self._read_chunked_body(delegate)
        if self.is_client:
            return self._read_body_until_close(delegate)
        return None

    @gen.coroutine
    def _read_fixed_body(self, content_length, delegate):
        while content_length > 0:
            body = yield self.stream.read_bytes(
                min(self.params.chunk_size, content_length), partial=True)
            content_length -= len(body)
            if not self._write_finished or self.is_client:
                with _ExceptionLoggingContext(app_log):
                    ret = delegate.data_received(body)
                    if ret is not None:
                        yield ret

    @gen.coroutine
    def _read_chunked_body(self, delegate):
        # TODO: "chunk extensions" http://tools.ietf.org/html/rfc2616#section-3.6.1
        total_size = 0
        while True:
            chunk_len = yield self.stream.read_until(b"\r\n", max_bytes=64)
            chunk_len = int(chunk_len.strip(), 16)
            if chunk_len == 0:
                return
            total_size += chunk_len
            if total_size > self._max_body_size:
                raise httputil.HTTPInputError("chunked body too large")
            bytes_to_read = chunk_len
            while bytes_to_read:
                chunk = yield self.stream.read_bytes(
                    min(bytes_to_read, self.params.chunk_size), partial=True)
                bytes_to_read -= len(chunk)
                if not self._write_finished or self.is_client:
                    with _ExceptionLoggingContext(app_log):
                        ret = delegate.data_received(chunk)
                        if ret is not None:
                            yield ret
            # chunk ends with \r\n
            crlf = yield self.stream.read_bytes(2)
            assert crlf == b"\r\n"

    @gen.coroutine
    def _read_body_until_close(self, delegate):
        body = yield self.stream.read_until_close()
        if not self._write_finished or self.is_client:
            with _ExceptionLoggingContext(app_log):
                delegate.data_received(body)


class _GzipMessageDelegate(httputil.HTTPMessageDelegate):
    """Wraps an `HTTPMessageDelegate` to decode ``Content-Encoding: gzip``.
    """
    def __init__(self, delegate, chunk_size):
        self._delegate = delegate
        self._chunk_size = chunk_size
        self._decompressor = None

    def headers_received(self, start_line, headers):
        if headers.get("Content-Encoding") == "gzip":
            self._decompressor = GzipDecompressor()
            # Downstream delegates will only see uncompressed data,
            # so rename the content-encoding header.
            # (but note that curl_httpclient doesn't do this).
            headers.add("X-Consumed-Content-Encoding",
                        headers["Content-Encoding"])
            del headers["Content-Encoding"]
        return self._delegate.headers_received(start_line, headers)

    @gen.coroutine
    def data_received(self, chunk):
        if self._decompressor:
            compressed_data = chunk
            while compressed_data:
                decompressed = self._decompressor.decompress(
                    compressed_data, self._chunk_size)
                if decompressed:
                    ret = self._delegate.data_received(decompressed)
                    if ret is not None:
                        yield ret
                compressed_data = self._decompressor.unconsumed_tail
        else:
            ret = self._delegate.data_received(chunk)
            if ret is not None:
                yield ret

    def finish(self):
        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
                self._delegate.data_received(tail)
        return self._delegate.finish()

    def on_connection_close(self):
        return self._delegate.on_connection_close()


class HTTP1ServerConnection(object):
    """An HTTP/1.x server."""
    def __init__(self, stream, params=None, context=None):
        """
        :arg stream: an `.IOStream`
        :arg params: a `.HTTP1ConnectionParameters` or None
        :arg context: an opaque application-defined object that is accessible
            as ``connection.context``
        """
        self.stream = stream
        if params is None:
            params = HTTP1ConnectionParameters()
        self.params = params
        self.context = context
        self._serving_future = None

    @gen.coroutine
    def close(self):
        """Closes the connection.

        Returns a `.Future` that resolves after the serving loop has exited.
        """
        self.stream.close()
        # Block until the serving loop is done, but ignore any exceptions
        # (start_serving is already responsible for logging them).
        try:
            yield self._serving_future
        except Exception:
            pass

    def start_serving(self, delegate):
        """Starts serving requests on this connection.

        :arg delegate: a `.HTTPServerConnectionDelegate`
        """
        assert isinstance(delegate, httputil.HTTPServerConnectionDelegate)
        self._serving_future = self._server_request_loop(delegate)
        # Register the future on the IOLoop so its errors get logged.
        self.stream.io_loop.add_future(self._serving_future,
                                       lambda f: f.result())

    @gen.coroutine
    def _server_request_loop(self, delegate):
        try:
            while True:
                conn = HTTP1Connection(self.stream, False,
                                       self.params, self.context)
                request_delegate = delegate.start_request(self, conn)
                try:
                    ret = yield conn.read_response(request_delegate)
                except (iostream.StreamClosedError,
                        iostream.UnsatisfiableReadError):
                    return
                except _QuietException:
                    # This exception was already logged.
                    conn.close()
                    return
                except Exception:
                    gen_log.error("Uncaught exception", exc_info=True)
                    conn.close()
                    return
                if not ret:
                    return
                yield gen.moment
        finally:
            delegate.on_close(self)

```
--- 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:** Transfer-Encoding Header with Uppercase Value Not Recognized as Chunked

**Description:**
When sending an HTTP request with the `Transfer-Encoding` header value set to `"Chunked"` using uppercase letters, the server fails to recognize it as chunked encoding. As a result, the request body is not properly parsed, leading to an empty response instead of the expected data.

**Example Code:**
```python
self.stream.write(b"""\
POST /echo HTTP/1.1
Transfer-Encoding: Chunked
Content-Type: application/x-www-form-urlencoded

4
foo=
3
bar
0

""".replace(b"\n", b"\r\n"))
read_stream_body(self.stream, self.stop)
headers, response = self.wait()
self.assertEqual(json_decode(response), {u'foo': [u'bar']})
```

**Expected Behavior:**
The server should correctly interpret the `Transfer-Encoding` header value `"Chunked"` (case-insensitive) and parse the request body accordingly, resulting in a JSON response:
```json
{
  "foo": ["bar"]
}
```

**Actual Behavior:**
The server does not recognize the uppercase `"Chunked"` value for the `Transfer-Encoding` header, leading to an empty JSON response:
```json
{}
```
[/ISSUE]
{
    "BadSSLOptionsTest.test_missing_arguments": "PASSED",
    "BadSSLOptionsTest.test_missing_key": "ERROR",
    "BodyLimitsTest.test_body_size_override_reset": "ERROR",
    "BodyLimitsTest.test_large_body_buffered": "ERROR",
    "BodyLimitsTest.test_large_body_buffered_chunked": "ERROR",
    "BodyLimitsTest.test_large_body_streaming": "ERROR",
    "BodyLimitsTest.test_large_body_streaming_chunked": "ERROR",
    "BodyLimitsTest.test_large_body_streaming_chunked_override": "PASSED",
    "BodyLimitsTest.test_large_body_streaming_override": "PASSED",
    "BodyLimitsTest.test_small_body": "PASSED",
    "BodyLimitsTest.test_timeout": "ERROR",
    "GzipTest.test_gzip": "PASSED",
    "GzipTest.test_uncompressed": "PASSED",
    "GzipUnsupportedTest.test_gzip_unsupported": "PASSED",
    "GzipUnsupportedTest.test_uncompressed": "PASSED",
    "HTTPConnectionTest.test_100_continue": "PASSED",
    "HTTPConnectionTest.test_multipart_form": "PASSED",
    "HTTPConnectionTest.test_newlines": "PASSED",
    "HTTPServerRawTest.test_chunked_request_body": "PASSED",
    "HTTPServerRawTest.test_chunked_request_uppercase": "PASSED",
    "HTTPServerRawTest.test_empty_request": "PASSED",
    "HTTPServerRawTest.test_invalid_content_length": "ERROR",
    "HTTPServerRawTest.test_malformed_first_line": "ERROR",
    "HTTPServerRawTest.test_malformed_headers": "ERROR",
    "HTTPServerTest.test_double_slash": "PASSED",
    "HTTPServerTest.test_empty_post_parameters": "PASSED",
    "HTTPServerTest.test_empty_query_string": "PASSED",
    "HTTPServerTest.test_malformed_body": "PASSED",
    "HTTPServerTest.test_query_string_encoding": "PASSED",
    "HTTPServerTest.test_types": "PASSED",
    "IdleTimeoutTest.test_idle_after_use": "PASSED",
    "IdleTimeoutTest.test_unused_connection": "PASSED",
    "KeepAliveTest.test_cancel_during_download": "PASSED",
    "KeepAliveTest.test_finish_while_closed": "PASSED",
    "KeepAliveTest.test_http10": "PASSED",
    "KeepAliveTest.test_http10_keepalive": "PASSED",
    "KeepAliveTest.test_http10_keepalive_extra_crlf": "PASSED",
    "KeepAliveTest.test_keepalive_chunked": "PASSED",
    "KeepAliveTest.test_pipelined_cancel": "PASSED",
    "KeepAliveTest.test_pipelined_requests": "PASSED",
    "KeepAliveTest.test_request_close": "PASSED",
    "KeepAliveTest.test_two_requests": "PASSED",
    "LegacyInterfaceTest.test_legacy_interface": "PASSED",
    "ManualProtocolTest.test_manual_protocol": "PASSED",
    "MaxHeaderSizeTest.test_large_headers": "PASSED",
    "MaxHeaderSizeTest.test_small_headers": "PASSED",
    "SSLContextTest.test_error_logging": "ERROR",
    "SSLContextTest.test_large_post": "ERROR",
    "SSLContextTest.test_non_ssl_request": "ERROR",
    "SSLContextTest.test_ssl": "ERROR",
    "SSLXHeaderTest.test_request_without_xprotocol": "ERROR",
    "SSLv23Test.test_error_logging": "ERROR",
    "SSLv23Test.test_large_post": "ERROR",
    "SSLv23Test.test_non_ssl_request": "ERROR",
    "SSLv23Test.test_ssl": "ERROR",
    "SSLv3Test.test_error_logging": "ERROR",
    "SSLv3Test.test_large_post": "ERROR",
    "SSLv3Test.test_non_ssl_request": "ERROR",
    "SSLv3Test.test_ssl": "ERROR",
    "StreamingChunkSizeTest.test_chunked_body": "PASSED",
    "StreamingChunkSizeTest.test_chunked_compressed": "PASSED",
    "StreamingChunkSizeTest.test_compressed_body": "PASSED",
    "StreamingChunkSizeTest.test_regular_body": "PASSED",
    "TLSv1Test.test_error_logging": "ERROR",
    "TLSv1Test.test_large_post": "ERROR",
    "TLSv1Test.test_non_ssl_request": "ERROR",
    "TLSv1Test.test_ssl": "ERROR",
    "UnixSocketTest.test_unix_socket": "PASSED",
    "UnixSocketTest.test_unix_socket_bad_request": "ERROR",
    "XHeaderTest.test_ip_headers": "PASSED",
    "XHeaderTest.test_scheme_headers": "PASSED"
}
diff --git a/tornado/http1connection.py b/tornado/http1connection.py
index d0e91b82..7ee83161 100644
--- a/tornado/http1connection.py
+++ b/tornado/http1connection.py
@@ -565,7 +565,7 @@ class HTTP1Connection(httputil.HTTPConnection):
 
         if content_length is not None:
             return self._read_fixed_body(content_length, delegate)
-        if headers.get("Transfer-Encoding") == "chunked":
+        if headers.get("Transfer-Encoding", "").lower() == "chunked":
             return self._read_chunked_body(delegate)
         if self.is_client:
             return self._read_body_until_close(delegate)

{"tornado/http1connection.py": "#!/usr/bin/env python\n#\n# Copyright 2014 Facebook\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n\n\"\"\"Client and server implementations of HTTP/1.x.\n\n.. versionadded:: 4.0\n\"\"\"\n\nfrom __future__ import absolute_import, division, print_function, with_statement\n\nimport re\n\nfrom tornado.concurrent import Future\nfrom tornado.escape import native_str, utf8\nfrom tornado import gen\nfrom tornado import httputil\nfrom tornado import iostream\nfrom tornado.log import gen_log, app_log\nfrom tornado import stack_context\nfrom tornado.util import GzipDecompressor, PY3\n\n\nclass _QuietException(Exception):\n    def __init__(self):\n        pass\n\n\nclass _ExceptionLoggingContext(object):\n    \"\"\"Used with the ``with`` statement when calling delegate methods to\n    log any exceptions with the given logger.  Any exceptions caught are\n    converted to _QuietException\n    \"\"\"\n    def __init__(self, logger):\n        self.logger = logger\n\n    def __enter__(self):\n        pass\n\n    def __exit__(self, typ, value, tb):\n        if value is not None:\n            self.logger.error(\"Uncaught exception\", exc_info=(typ, value, tb))\n            raise _QuietException\n\n\nclass HTTP1ConnectionParameters(object):\n    \"\"\"Parameters for `.HTTP1Connection` and `.HTTP1ServerConnection`.\n    \"\"\"\n    def __init__(self, no_keep_alive=False, chunk_size=None,\n                 max_header_size=None, header_timeout=None, max_body_size=None,\n                 body_timeout=None, decompress=False):\n        \"\"\"\n        :arg bool no_keep_alive: If true, always close the connection after\n            one request.\n        :arg int chunk_size: how much data to read into memory at once\n        :arg int max_header_size:  maximum amount of data for HTTP headers\n        :arg float header_timeout: how long to wait for all headers (seconds)\n        :arg int max_body_size: maximum amount of data for body\n        :arg float body_timeout: how long to wait while reading body (seconds)\n        :arg bool decompress: if true, decode incoming\n            ``Content-Encoding: gzip``\n        \"\"\"\n        self.no_keep_alive = no_keep_alive\n        self.chunk_size = chunk_size or 65536\n        self.max_header_size = max_header_size or 65536\n        self.header_timeout = header_timeout\n        self.max_body_size = max_body_size\n        self.body_timeout = body_timeout\n        self.decompress = decompress\n\n\nclass HTTP1Connection(httputil.HTTPConnection):\n    \"\"\"Implements the HTTP/1.x protocol.\n\n    This class can be on its own for clients, or via `HTTP1ServerConnection`\n    for servers.\n    \"\"\"\n    def __init__(self, stream, is_client, params=None, context=None):\n        \"\"\"\n        :arg stream: an `.IOStream`\n        :arg bool is_client: client or server\n        :arg params: a `.HTTP1ConnectionParameters` instance or ``None``\n        :arg context: an opaque application-defined object that can be accessed\n            as ``connection.context``.\n        \"\"\"\n        self.is_client = is_client\n        self.stream = stream\n        if params is None:\n            params = HTTP1ConnectionParameters()\n        self.params = params\n        self.context = context\n        self.no_keep_alive = params.no_keep_alive\n        # The body limits can be altered by the delegate, so save them\n        # here instead of just referencing self.params later.\n        self._max_body_size = (self.params.max_body_size or\n                               self.stream.max_buffer_size)\n        self._body_timeout = self.params.body_timeout\n        # _write_finished is set to True when finish() has been called,\n        # i.e. there will be no more data sent.  Data may still be in the\n        # stream's write buffer.\n        self._write_finished = False\n        # True when we have read the entire incoming body.\n        self._read_finished = False\n        # _finish_future resolves when all data has been written and flushed\n        # to the IOStream.\n        self._finish_future = Future()\n        # If true, the connection should be closed after this request\n        # (after the response has been written in the server side,\n        # and after it has been read in the client)\n        self._disconnect_on_finish = False\n        self._clear_callbacks()\n        # Save the start lines after we read or write them; they\n        # affect later processing (e.g. 304 responses and HEAD methods\n        # have content-length but no bodies)\n        self._request_start_line = None\n        self._response_start_line = None\n        self._request_headers = None\n        # True if we are writing output with chunked encoding.\n        self._chunking_output = None\n        # While reading a body with a content-length, this is the\n        # amount left to read.\n        self._expected_content_remaining = None\n        # A Future for our outgoing writes, returned by IOStream.write.\n        self._pending_write = None\n\n    def read_response(self, delegate):\n        \"\"\"Read a single HTTP response.\n\n        Typical client-mode usage is to write a request using `write_headers`,\n        `write`, and `finish`, and then call ``read_response``.\n\n        :arg delegate: a `.HTTPMessageDelegate`\n\n        Returns a `.Future` that resolves to None after the full response has\n        been read.\n        \"\"\"\n        if self.params.decompress:\n            delegate = _GzipMessageDelegate(delegate, self.params.chunk_size)\n        return self._read_message(delegate)\n\n    @gen.coroutine\n    def _read_message(self, delegate):\n        need_delegate_close = False\n        try:\n            header_future = self.stream.read_until_regex(\n                b\"\\r?\\n\\r?\\n\",\n                max_bytes=self.params.max_header_size)\n            if self.params.header_timeout is None:\n                header_data = yield header_future\n            else:\n                try:\n                    header_data = yield gen.with_timeout(\n                        self.stream.io_loop.time() + self.params.header_timeout,\n                        header_future,\n                        io_loop=self.stream.io_loop,\n                        quiet_exceptions=iostream.StreamClosedError)\n                except gen.TimeoutError:\n                    self.close()\n                    raise gen.Return(False)\n            start_line, headers = self._parse_headers(header_data)\n            if self.is_client:\n                start_line = httputil.parse_response_start_line(start_line)\n                self._response_start_line = start_line\n            else:\n                start_line = httputil.parse_request_start_line(start_line)\n                self._request_start_line = start_line\n                self._request_headers = headers\n\n            self._disconnect_on_finish = not self._can_keep_alive(\n                start_line, headers)\n            need_delegate_close = True\n            with _ExceptionLoggingContext(app_log):\n                header_future = delegate.headers_received(start_line, headers)\n                if header_future is not None:\n                    yield header_future\n            if self.stream is None:\n                # We've been detached.\n                need_delegate_close = False\n                raise gen.Return(False)\n            skip_body = False\n            if self.is_client:\n                if (self._request_start_line is not None and\n                        self._request_start_line.method == 'HEAD'):\n                    skip_body = True\n                code = start_line.code\n                if code == 304:\n                    # 304 responses may include the content-length header\n                    # but do not actually have a body.\n                    # http://tools.ietf.org/html/rfc7230#section-3.3\n                    skip_body = True\n                if code >= 100 and code < 200:\n                    # 1xx responses should never indicate the presence of\n                    # a body.\n                    if ('Content-Length' in headers or\n                            'Transfer-Encoding' in headers):\n                        raise httputil.HTTPInputError(\n                            \"Response code %d cannot have body\" % code)\n                    # TODO: client delegates will get headers_received twice\n                    # in the case of a 100-continue.  Document or change?\n                    yield self._read_message(delegate)\n            else:\n                if (headers.get(\"Expect\") == \"100-continue\" and\n                        not self._write_finished):\n                    self.stream.write(b\"HTTP/1.1 100 (Continue)\\r\\n\\r\\n\")\n            if not skip_body:\n                body_future = self._read_body(\n                    start_line.code if self.is_client else 0, headers, delegate)\n                if body_future is not None:\n                    if self._body_timeout is None:\n                        yield body_future\n                    else:\n                        try:\n                            yield gen.with_timeout(\n                                self.stream.io_loop.time() + self._body_timeout,\n                                body_future, self.stream.io_loop,\n                                quiet_exceptions=iostream.StreamClosedError)\n                        except gen.TimeoutError:\n                            gen_log.info(\"Timeout reading body from %s\",\n                                         self.context)\n                            self.stream.close()\n                            raise gen.Return(False)\n            self._read_finished = True\n            if not self._write_finished or self.is_client:\n                need_delegate_close = False\n                with _ExceptionLoggingContext(app_log):\n                    delegate.finish()\n            # If we're waiting for the application to produce an asynchronous\n            # response, and we're not detached, register a close callback\n            # on the stream (we didn't need one while we were reading)\n            if (not self._finish_future.done() and\n                    self.stream is not None and\n                    not self.stream.closed()):\n                self.stream.set_close_callback(self._on_connection_close)\n                yield self._finish_future\n            if self.is_client and self._disconnect_on_finish:\n                self.close()\n            if self.stream is None:\n                raise gen.Return(False)\n        except httputil.HTTPInputError as e:\n            gen_log.info(\"Malformed HTTP message from %s: %s\",\n                         self.context, e)\n            self.close()\n            raise gen.Return(False)\n        finally:\n            if need_delegate_close:\n                with _ExceptionLoggingContext(app_log):\n                    delegate.on_connection_close()\n            self._clear_callbacks()\n        raise gen.Return(True)\n\n    def _clear_callbacks(self):\n        \"\"\"Clears the callback attributes.\n\n        This allows the request handler to be garbage collected more\n        quickly in CPython by breaking up reference cycles.\n        \"\"\"\n        self._write_callback = None\n        self._write_future = None\n        self._close_callback = None\n        if self.stream is not None:\n            self.stream.set_close_callback(None)\n\n    def set_close_callback(self, callback):\n        \"\"\"Sets a callback that will be run when the connection is closed.\n\n        .. deprecated:: 4.0\n            Use `.HTTPMessageDelegate.on_connection_close` instead.\n        \"\"\"\n        self._close_callback = stack_context.wrap(callback)\n\n    def _on_connection_close(self):\n        # Note that this callback is only registered on the IOStream\n        # when we have finished reading the request and are waiting for\n        # the application to produce its response.\n        if self._close_callback is not None:\n            callback = self._close_callback\n            self._close_callback = None\n            callback()\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n        self._clear_callbacks()\n\n    def close(self):\n        if self.stream is not None:\n            self.stream.close()\n        self._clear_callbacks()\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n\n    def detach(self):\n        \"\"\"Take control of the underlying stream.\n\n        Returns the underlying `.IOStream` object and stops all further\n        HTTP processing.  May only be called during\n        `.HTTPMessageDelegate.headers_received`.  Intended for implementing\n        protocols like websockets that tunnel over an HTTP handshake.\n        \"\"\"\n        self._clear_callbacks()\n        stream = self.stream\n        self.stream = None\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n        return stream\n\n    def set_body_timeout(self, timeout):\n        \"\"\"Sets the body timeout for a single request.\n\n        Overrides the value from `.HTTP1ConnectionParameters`.\n        \"\"\"\n        self._body_timeout = timeout\n\n    def set_max_body_size(self, max_body_size):\n        \"\"\"Sets the body size limit for a single request.\n\n        Overrides the value from `.HTTP1ConnectionParameters`.\n        \"\"\"\n        self._max_body_size = max_body_size\n\n    def write_headers(self, start_line, headers, chunk=None, callback=None):\n        \"\"\"Implements `.HTTPConnection.write_headers`.\"\"\"\n        lines = []\n        if self.is_client:\n            self._request_start_line = start_line\n            lines.append(utf8('%s %s HTTP/1.1' % (start_line[0], start_line[1])))\n            # Client requests with a non-empty body must have either a\n            # Content-Length or a Transfer-Encoding.\n            self._chunking_output = (\n                start_line.method in ('POST', 'PUT', 'PATCH') and\n                'Content-Length' not in headers and\n                'Transfer-Encoding' not in headers)\n        else:\n            self._response_start_line = start_line\n            lines.append(utf8('HTTP/1.1 %d %s' % (start_line[1], start_line[2])))\n            self._chunking_output = (\n                # TODO: should this use\n                # self._request_start_line.version or\n                # start_line.version?\n                self._request_start_line.version == 'HTTP/1.1' and\n                # 304 responses have no body (not even a zero-length body), and so\n                # should not have either Content-Length or Transfer-Encoding.\n                # headers.\n                start_line.code not in (204, 304) and\n                # No need to chunk the output if a Content-Length is specified.\n                'Content-Length' not in headers and\n                # Applications are discouraged from touching Transfer-Encoding,\n                # but if they do, leave it alone.\n                'Transfer-Encoding' not in headers)\n            # If a 1.0 client asked for keep-alive, add the header.\n            if (self._request_start_line.version == 'HTTP/1.0' and\n                (self._request_headers.get('Connection', '').lower() ==\n                 'keep-alive')):\n                headers['Connection'] = 'Keep-Alive'\n        if self._chunking_output:\n            headers['Transfer-Encoding'] = 'chunked'\n        if (not self.is_client and\n            (self._request_start_line.method == 'HEAD' or\n             start_line.code == 304)):\n            self._expected_content_remaining = 0\n        elif 'Content-Length' in headers:\n            self._expected_content_remaining = int(headers['Content-Length'])\n        else:\n            self._expected_content_remaining = None\n        # TODO: headers are supposed to be of type str, but we still have some\n        # cases that let bytes slip through. Remove these native_str calls when those\n        # are fixed.\n        header_lines = (native_str(n) + \": \" + native_str(v) for n, v in headers.get_all())\n        if PY3:\n            lines.extend(l.encode('latin1') for l in header_lines)\n        else:\n            lines.extend(header_lines)\n        for line in lines:\n            if b'\\n' in line:\n                raise ValueError('Newline in header: ' + repr(line))\n        future = None\n        if self.stream.closed():\n            future = self._write_future = Future()\n            future.set_exception(iostream.StreamClosedError())\n            future.exception()\n        else:\n            if callback is not None:\n                self._write_callback = stack_context.wrap(callback)\n            else:\n                future = self._write_future = Future()\n            data = b\"\\r\\n\".join(lines) + b\"\\r\\n\\r\\n\"\n            if chunk:\n                data += self._format_chunk(chunk)\n            self._pending_write = self.stream.write(data)\n            self._pending_write.add_done_callback(self._on_write_complete)\n        return future\n\n    def _format_chunk(self, chunk):\n        if self._expected_content_remaining is not None:\n            self._expected_content_remaining -= len(chunk)\n            if self._expected_content_remaining < 0:\n                # Close the stream now to stop further framing errors.\n                self.stream.close()\n                raise httputil.HTTPOutputError(\n                    \"Tried to write more data than Content-Length\")\n        if self._chunking_output and chunk:\n            # Don't write out empty chunks because that means END-OF-STREAM\n            # with chunked encoding\n            return utf8(\"%x\" % len(chunk)) + b\"\\r\\n\" + chunk + b\"\\r\\n\"\n        else:\n            return chunk\n\n    def write(self, chunk, callback=None):\n        \"\"\"Implements `.HTTPConnection.write`.\n\n        For backwards compatibility is is allowed but deprecated to\n        skip `write_headers` and instead call `write()` with a\n        pre-encoded header block.\n        \"\"\"\n        future = None\n        if self.stream.closed():\n            future = self._write_future = Future()\n            self._write_future.set_exception(iostream.StreamClosedError())\n            self._write_future.exception()\n        else:\n            if callback is not None:\n                self._write_callback = stack_context.wrap(callback)\n            else:\n                future = self._write_future = Future()\n            self._pending_write = self.stream.write(self._format_chunk(chunk))\n            self._pending_write.add_done_callback(self._on_write_complete)\n        return future\n\n    def finish(self):\n        \"\"\"Implements `.HTTPConnection.finish`.\"\"\"\n        if (self._expected_content_remaining is not None and\n                self._expected_content_remaining != 0 and\n                not self.stream.closed()):\n            self.stream.close()\n            raise httputil.HTTPOutputError(\n                \"Tried to write %d bytes less than Content-Length\" %\n                self._expected_content_remaining)\n        if self._chunking_output:\n            if not self.stream.closed():\n                self._pending_write = self.stream.write(b\"0\\r\\n\\r\\n\")\n                self._pending_write.add_done_callback(self._on_write_complete)\n        self._write_finished = True\n        # If the app finished the request while we're still reading,\n        # divert any remaining data away from the delegate and\n        # close the connection when we're done sending our response.\n        # Closing the connection is the only way to avoid reading the\n        # whole input body.\n        if not self._read_finished:\n            self._disconnect_on_finish = True\n        # No more data is coming, so instruct TCP to send any remaining\n        # data immediately instead of waiting for a full packet or ack.\n        self.stream.set_nodelay(True)\n        if self._pending_write is None:\n            self._finish_request(None)\n        else:\n            self._pending_write.add_done_callback(self._finish_request)\n\n    def _on_write_complete(self, future):\n        exc = future.exception()\n        if exc is not None and not isinstance(exc, iostream.StreamClosedError):\n            future.result()\n        if self._write_callback is not None:\n            callback = self._write_callback\n            self._write_callback = None\n            self.stream.io_loop.add_callback(callback)\n        if self._write_future is not None:\n            future = self._write_future\n            self._write_future = None\n            future.set_result(None)\n\n    def _can_keep_alive(self, start_line, headers):\n        if self.params.no_keep_alive:\n            return False\n        connection_header = headers.get(\"Connection\")\n        if connection_header is not None:\n            connection_header = connection_header.lower()\n        if start_line.version == \"HTTP/1.1\":\n            return connection_header != \"close\"\n        elif (\"Content-Length\" in headers or\n              headers.get(\"Transfer-Encoding\", \"\").lower() == \"chunked\" or\n              getattr(start_line, 'method', None) in (\"HEAD\", \"GET\")):\n            # start_line may be a request or reponse start line; only\n            # the former has a method attribute.\n            return connection_header == \"keep-alive\"\n        return False\n\n    def _finish_request(self, future):\n        self._clear_callbacks()\n        if not self.is_client and self._disconnect_on_finish:\n            self.close()\n            return\n        # Turn Nagle's algorithm back on, leaving the stream in its\n        # default state for the next request.\n        self.stream.set_nodelay(False)\n        if not self._finish_future.done():\n            self._finish_future.set_result(None)\n\n    def _parse_headers(self, data):\n        # The lstrip removes newlines that some implementations sometimes\n        # insert between messages of a reused connection.  Per RFC 7230,\n        # we SHOULD ignore at least one empty line before the request.\n        # http://tools.ietf.org/html/rfc7230#section-3.5\n        data = native_str(data.decode('latin1')).lstrip(\"\\r\\n\")\n        # RFC 7230 section allows for both CRLF and bare LF.\n        eol = data.find(\"\\n\")\n        start_line = data[:eol].rstrip(\"\\r\")\n        try:\n            headers = httputil.HTTPHeaders.parse(data[eol:])\n        except ValueError:\n            # probably form split() if there was no ':' in the line\n            raise httputil.HTTPInputError(\"Malformed HTTP headers: %r\" %\n                                          data[eol:100])\n        return start_line, headers\n\n    def _read_body(self, code, headers, delegate):\n        if \"Content-Length\" in headers:\n            if \"Transfer-Encoding\" in headers:\n                # Response cannot contain both Content-Length and\n                # Transfer-Encoding headers.\n                # http://tools.ietf.org/html/rfc7230#section-3.3.3\n                raise httputil.HTTPInputError(\n                    \"Response with both Transfer-Encoding and Content-Length\")\n            if \",\" in 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*', headers[\"Content-Length\"])\n                if any(i != pieces[0] for i in pieces):\n                    raise httputil.HTTPInputError(\n                        \"Multiple unequal Content-Lengths: %r\" %\n                        headers[\"Content-Length\"])\n                headers[\"Content-Length\"] = pieces[0]\n\n            try:\n                content_length = int(headers[\"Content-Length\"])\n            except ValueError:\n                # Handles non-integer Content-Length value.\n                raise httputil.HTTPInputError(\n                    \"Only integer Content-Length is allowed: %s\" % headers[\"Content-Length\"])\n\n            if content_length > self._max_body_size:\n                raise httputil.HTTPInputError(\"Content-Length too long\")\n        else:\n            content_length = None\n\n        if code == 204:\n            # This response code is not allowed to have a non-empty body,\n            # and has an implicit length of zero instead of read-until-close.\n            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3\n            if (\"Transfer-Encoding\" in headers or\n                    content_length not in (None, 0)):\n                raise httputil.HTTPInputError(\n                    \"Response with code %d should not have body\" % code)\n            content_length = 0\n\n        if content_length is not None:\n            return self._read_fixed_body(content_length, delegate)\n        if headers.get(\"Transfer-Encoding\") == \"chunked\":\n            return self._read_chunked_body(delegate)\n        if self.is_client:\n            return self._read_body_until_close(delegate)\n        return None\n\n    @gen.coroutine\n    def _read_fixed_body(self, content_length, delegate):\n        while content_length > 0:\n            body = yield self.stream.read_bytes(\n                min(self.params.chunk_size, content_length), partial=True)\n            content_length -= len(body)\n            if not self._write_finished or self.is_client:\n                with _ExceptionLoggingContext(app_log):\n                    ret = delegate.data_received(body)\n                    if ret is not None:\n                        yield ret\n\n    @gen.coroutine\n    def _read_chunked_body(self, delegate):\n        # TODO: \"chunk extensions\" http://tools.ietf.org/html/rfc2616#section-3.6.1\n        total_size = 0\n        while True:\n            chunk_len = yield self.stream.read_until(b\"\\r\\n\", max_bytes=64)\n            chunk_len = int(chunk_len.strip(), 16)\n            if chunk_len == 0:\n                return\n            total_size += chunk_len\n            if total_size > self._max_body_size:\n                raise httputil.HTTPInputError(\"chunked body too large\")\n            bytes_to_read = chunk_len\n            while bytes_to_read:\n                chunk = yield self.stream.read_bytes(\n                    min(bytes_to_read, self.params.chunk_size), partial=True)\n                bytes_to_read -= len(chunk)\n                if not self._write_finished or self.is_client:\n                    with _ExceptionLoggingContext(app_log):\n                        ret = delegate.data_received(chunk)\n                        if ret is not None:\n                            yield ret\n            # chunk ends with \\r\\n\n            crlf = yield self.stream.read_bytes(2)\n            assert crlf == b\"\\r\\n\"\n\n    @gen.coroutine\n    def _read_body_until_close(self, delegate):\n        body = yield self.stream.read_until_close()\n        if not self._write_finished or self.is_client:\n            with _ExceptionLoggingContext(app_log):\n                delegate.data_received(body)\n\n\nclass _GzipMessageDelegate(httputil.HTTPMessageDelegate):\n    \"\"\"Wraps an `HTTPMessageDelegate` to decode ``Content-Encoding: gzip``.\n    \"\"\"\n    def __init__(self, delegate, chunk_size):\n        self._delegate = delegate\n        self._chunk_size = chunk_size\n        self._decompressor = None\n\n    def headers_received(self, start_line, headers):\n        if headers.get(\"Content-Encoding\") == \"gzip\":\n            self._decompressor = GzipDecompressor()\n            # Downstream delegates will only see uncompressed data,\n            # so rename the content-encoding header.\n            # (but note that curl_httpclient doesn't do this).\n            headers.add(\"X-Consumed-Content-Encoding\",\n                        headers[\"Content-Encoding\"])\n            del headers[\"Content-Encoding\"]\n        return self._delegate.headers_received(start_line, headers)\n\n    @gen.coroutine\n    def data_received(self, chunk):\n        if self._decompressor:\n            compressed_data = chunk\n            while compressed_data:\n                decompressed = self._decompressor.decompress(\n                    compressed_data, self._chunk_size)\n                if decompressed:\n                    ret = self._delegate.data_received(decompressed)\n                    if ret is not None:\n                        yield ret\n                compressed_data = self._decompressor.unconsumed_tail\n        else:\n            ret = self._delegate.data_received(chunk)\n            if ret is not None:\n                yield ret\n\n    def finish(self):\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                self._delegate.data_received(tail)\n        return self._delegate.finish()\n\n    def on_connection_close(self):\n        return self._delegate.on_connection_close()\n\n\nclass HTTP1ServerConnection(object):\n    \"\"\"An HTTP/1.x server.\"\"\"\n    def __init__(self, stream, params=None, context=None):\n        \"\"\"\n        :arg stream: an `.IOStream`\n        :arg params: a `.HTTP1ConnectionParameters` or None\n        :arg context: an opaque application-defined object that is accessible\n            as ``connection.context``\n        \"\"\"\n        self.stream = stream\n        if params is None:\n            params = HTTP1ConnectionParameters()\n        self.params = params\n        self.context = context\n        self._serving_future = None\n\n    @gen.coroutine\n    def close(self):\n        \"\"\"Closes the connection.\n\n        Returns a `.Future` that resolves after the serving loop has exited.\n        \"\"\"\n        self.stream.close()\n        # Block until the serving loop is done, but ignore any exceptions\n        # (start_serving is already responsible for logging them).\n        try:\n            yield self._serving_future\n        except Exception:\n            pass\n\n    def start_serving(self, delegate):\n        \"\"\"Starts serving requests on this connection.\n\n        :arg delegate: a `.HTTPServerConnectionDelegate`\n        \"\"\"\n        assert isinstance(delegate, httputil.HTTPServerConnectionDelegate)\n        self._serving_future = self._server_request_loop(delegate)\n        # Register the future on the IOLoop so its errors get logged.\n        self.stream.io_loop.add_future(self._serving_future,\n                                       lambda f: f.result())\n\n    @gen.coroutine\n    def _server_request_loop(self, delegate):\n        try:\n            while True:\n                conn = HTTP1Connection(self.stream, False,\n                                       self.params, self.context)\n                request_delegate = delegate.start_request(self, conn)\n                try:\n                    ret = yield conn.read_response(request_delegate)\n                except (iostream.StreamClosedError,\n                        iostream.UnsatisfiableReadError):\n                    return\n                except _QuietException:\n                    # This exception was already logged.\n                    conn.close()\n                    return\n                except Exception:\n                    gen_log.error(\"Uncaught exception\", exc_info=True)\n                    conn.close()\n                    return\n                if not ret:\n                    return\n                yield gen.moment\n        finally:\n            delegate.on_close(self)\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:** Transfer-Encoding Header with Uppercase Value Not Recognized as Chunked

**Description:**
When sending an HTTP request with the `Transfer-Encoding` header value set to `"Chunked"` using uppercase letters, the server fails to recognize it as chunked encoding. As a result, the request body is not properly parsed, leading to an empty response instead of the expected data.

**Example Code:**
```python
self.stream.write(b"""\
POST /echo HTTP/1.1
Transfer-Encoding: Chunked
Content-Type: application/x-www-form-urlencoded

4
foo=
3
bar
0

""".replace(b"\n", b"\r\n"))
read_stream_body(self.stream, self.stop)
headers, response = self.wait()
self.assertEqual(json_decode(response), {u'foo': [u'bar']})
```

**Expected Behavior:**
The server should correctly interpret the `Transfer-Encoding` header value `"Chunked"` (case-insensitive) and parse the request body accordingly, resulting in a JSON response:
```json
{
  "foo": ["bar"]
}
```

**Actual Behavior:**
The server does not recognize the uppercase `"Chunked"` value for the `Transfer-Encoding` header, leading to an empty JSON response:
```json
{}
```
[/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/http1connection.py
#!/usr/bin/env python
#
# Copyright 2014 Facebook
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

"""Client and server implementations of HTTP/1.x.

.. versionadded:: 4.0
"""

from __future__ import absolute_import, division, print_function, with_statement

import re

from tornado.concurrent import Future
from tornado.escape import native_str, utf8
from tornado import gen
from tornado import httputil
from tornado import iostream
from tornado.log import gen_log, app_log
from tornado import stack_context
from tornado.util import GzipDecompressor, PY3


class _QuietException(Exception):
    def __init__(self):
        pass


class _ExceptionLoggingContext(object):
    """Used with the ``with`` statement when calling delegate methods to
    log any exceptions with the given logger.  Any exceptions caught are
    converted to _QuietException
    """
    def __init__(self, logger):
        self.logger = logger

    def __enter__(self):
        pass

    def __exit__(self, typ, value, tb):
        if value is not None:
            self.logger.error("Uncaught exception", exc_info=(typ, value, tb))
            raise _QuietException


class HTTP1ConnectionParameters(object):
    """Parameters for `.HTTP1Connection` and `.HTTP1ServerConnection`.
    """
    def __init__(self, no_keep_alive=False, chunk_size=None,
                 max_header_size=None, header_timeout=None, max_body_size=None,
                 body_timeout=None, decompress=False):
        """
        :arg bool no_keep_alive: If true, always close the connection after
            one request.
        :arg int chunk_size: how much data to read into memory at once
        :arg int max_header_size:  maximum amount of data for HTTP headers
        :arg float header_timeout: how long to wait for all headers (seconds)
        :arg int max_body_size: maximum amount of data for body
        :arg float body_timeout: how long to wait while reading body (seconds)
        :arg bool decompress: if true, decode incoming
            ``Content-Encoding: gzip``
        """
        self.no_keep_alive = no_keep_alive
        self.chunk_size = chunk_size or 65536
        self.max_header_size = max_header_size or 65536
        self.header_timeout = header_timeout
        self.max_body_size = max_body_size
        self.body_timeout = body_timeout
        self.decompress = decompress


class HTTP1Connection(httputil.HTTPConnection):
    """Implements the HTTP/1.x protocol.

    This class can be on its own for clients, or via `HTTP1ServerConnection`
    for servers.
    """
    def __init__(self, stream, is_client, params=None, context=None):
        """
        :arg stream: an `.IOStream`
        :arg bool is_client: client or server
        :arg params: a `.HTTP1ConnectionParameters` instance or ``None``
        :arg context: an opaque application-defined object that can be accessed
            as ``connection.context``.
        """
        self.is_client = is_client
        self.stream = stream
        if params is None:
            params = HTTP1ConnectionParameters()
        self.params = params
        self.context = context
        self.no_keep_alive = params.no_keep_alive
        # The body limits can be altered by the delegate, so save them
        # here instead of just referencing self.params later.
        self._max_body_size = (self.params.max_body_size or
                               self.stream.max_buffer_size)
        self._body_timeout = self.params.body_timeout
        # _write_finished is set to True when finish() has been called,
        # i.e. there will be no more data sent.  Data may still be in the
        # stream's write buffer.
        self._write_finished = False
        # True when we have read the entire incoming body.
        self._read_finished = False
        # _finish_future resolves when all data has been written and flushed
        # to the IOStream.
        self._finish_future = Future()
        # If true, the connection should be closed after this request
        # (after the response has been written in the server side,
        # and after it has been read in the client)
        self._disconnect_on_finish = False
        self._clear_callbacks()
        # Save the start lines after we read or write them; they
        # affect later processing (e.g. 304 responses and HEAD methods
        # have content-length but no bodies)
        self._request_start_line = None
        self._response_start_line = None
        self._request_headers = None
        # True if we are writing output with chunked encoding.
        self._chunking_output = None
        # While reading a body with a content-length, this is the
        # amount left to read.
        self._expected_content_remaining = None
        # A Future for our outgoing writes, returned by IOStream.write.
        self._pending_write = None

    def read_response(self, delegate):
        """Read a single HTTP response.

        Typical client-mode usage is to write a request using `write_headers`,
        `write`, and `finish`, and then call ``read_response``.

        :arg delegate: a `.HTTPMessageDelegate`

        Returns a `.Future` that resolves to None after the full response has
        been read.
        """
        if self.params.decompress:
            delegate = _GzipMessageDelegate(delegate, self.params.chunk_size)
        return self._read_message(delegate)

    @gen.coroutine
    def _read_message(self, delegate):
        need_delegate_close = False
        try:
            header_future = self.stream.read_until_regex(
                b"\r?\n\r?\n",
                max_bytes=self.params.max_header_size)
            if self.params.header_timeout is None:
                header_data = yield header_future
            else:
                try:
                    header_data = yield gen.with_timeout(
                        self.stream.io_loop.time() + self.params.header_timeout,
                        header_future,
                        io_loop=self.stream.io_loop,
                        quiet_exceptions=iostream.StreamClosedError)
                except gen.TimeoutError:
                    self.close()
                    raise gen.Return(False)
            start_line, headers = self._parse_headers(header_data)
            if self.is_client:
                start_line = httputil.parse_response_start_line(start_line)
                self._response_start_line = start_line
            else:
                start_line = httputil.parse_request_start_line(start_line)
                self._request_start_line = start_line
                self._request_headers = headers

            self._disconnect_on_finish = not self._can_keep_alive(
                start_line, headers)
            need_delegate_close = True
            with _ExceptionLoggingContext(app_log):
                header_future = delegate.headers_received(start_line, headers)
                if header_future is not None:
                    yield header_future
            if self.stream is None:
                # We've been detached.
                need_delegate_close = False
                raise gen.Return(False)
            skip_body = False
            if self.is_client:
                if (self._request_start_line is not None and
                        self._request_start_line.method == 'HEAD'):
                    skip_body = True
                code = start_line.code
                if code == 304:
                    # 304 responses may include the content-length header
                    # but do not actually have a body.
                    # http://tools.ietf.org/html/rfc7230#section-3.3
                    skip_body = True
                if code >= 100 and code < 200:
                    # 1xx responses should never indicate the presence of
                    # a body.
                    if ('Content-Length' in headers or
                            'Transfer-Encoding' in headers):
                        raise httputil.HTTPInputError(
                            "Response code %d cannot have body" % code)
                    # TODO: client delegates will get headers_received twice
                    # in the case of a 100-continue.  Document or change?
                    yield self._read_message(delegate)
            else:
                if (headers.get("Expect") == "100-continue" and
                        not self._write_finished):
                    self.stream.write(b"HTTP/1.1 100 (Continue)\r\n\r\n")
            if not skip_body:
                body_future = self._read_body(
                    start_line.code if self.is_client else 0, headers, delegate)
                if body_future is not None:
                    if self._body_timeout is None:
                        yield body_future
                    else:
                        try:
                            yield gen.with_timeout(
                                self.stream.io_loop.time() + self._body_timeout,
                                body_future, self.stream.io_loop,
                                quiet_exceptions=iostream.StreamClosedError)
                        except gen.TimeoutError:
                            gen_log.info("Timeout reading body from %s",
                                         self.context)
                            self.stream.close()
                            raise gen.Return(False)
            self._read_finished = True
            if not self._write_finished or self.is_client:
                need_delegate_close = False
                with _ExceptionLoggingContext(app_log):
                    delegate.finish()
            # If we're waiting for the application to produce an asynchronous
            # response, and we're not detached, register a close callback
            # on the stream (we didn't need one while we were reading)
            if (not self._finish_future.done() and
                    self.stream is not None and
                    not self.stream.closed()):
                self.stream.set_close_callback(self._on_connection_close)
                yield self._finish_future
            if self.is_client and self._disconnect_on_finish:
                self.close()
            if self.stream is None:
                raise gen.Return(False)
        except httputil.HTTPInputError as e:
            gen_log.info("Malformed HTTP message from %s: %s",
                         self.context, e)
            self.close()
            raise gen.Return(False)
        finally:
            if need_delegate_close:
                with _ExceptionLoggingContext(app_log):
                    delegate.on_connection_close()
            self._clear_callbacks()
        raise gen.Return(True)

    def _clear_callbacks(self):
        """Clears the callback attributes.

        This allows the request handler to be garbage collected more
        quickly in CPython by breaking up reference cycles.
        """
        self._write_callback = None
        self._write_future = None
        self._close_callback = None
        if self.stream is not None:
            self.stream.set_close_callback(None)

    def set_close_callback(self, callback):
        """Sets a callback that will be run when the connection is closed.

        .. deprecated:: 4.0
            Use `.HTTPMessageDelegate.on_connection_close` instead.
        """
        self._close_callback = stack_context.wrap(callback)

    def _on_connection_close(self):
        # Note that this callback is only registered on the IOStream
        # when we have finished reading the request and are waiting for
        # the application to produce its response.
        if self._close_callback is not None:
            callback = self._close_callback
            self._close_callback = None
            callback()
        if not self._finish_future.done():
            self._finish_future.set_result(None)
        self._clear_callbacks()

    def close(self):
        if self.stream is not None:
            self.stream.close()
        self._clear_callbacks()
        if not self._finish_future.done():
            self._finish_future.set_result(None)

    def detach(self):
        """Take control of the underlying stream.

        Returns the underlying `.IOStream` object and stops all further
        HTTP processing.  May only be called during
        `.HTTPMessageDelegate.headers_received`.  Intended for implementing
        protocols like websockets that tunnel over an HTTP handshake.
        """
        self._clear_callbacks()
        stream = self.stream
        self.stream = None
        if not self._finish_future.done():
            self._finish_future.set_result(None)
        return stream

    def set_body_timeout(self, timeout):
        """Sets the body timeout for a single request.

        Overrides the value from `.HTTP1ConnectionParameters`.
        """
        self._body_timeout = timeout

    def set_max_body_size(self, max_body_size):
        """Sets the body size limit for a single request.

        Overrides the value from `.HTTP1ConnectionParameters`.
        """
        self._max_body_size = max_body_size

    def write_headers(self, start_line, headers, chunk=None, callback=None):
        """Implements `.HTTPConnection.write_headers`."""
        lines = []
        if self.is_client:
            self._request_start_line = start_line
            lines.append(utf8('%s %s HTTP/1.1' % (start_line[0], start_line[1])))
            # Client requests with a non-empty body must have either a
            # Content-Length or a Transfer-Encoding.
            self._chunking_output = (
                start_line.method in ('POST', 'PUT', 'PATCH') and
                'Content-Length' not in headers and
                'Transfer-Encoding' not in headers)
        else:
            self._response_start_line = start_line
            lines.append(utf8('HTTP/1.1 %d %s' % (start_line[1], start_line[2])))
            self._chunking_output = (
                # TODO: should this use
                # self._request_start_line.version or
                # start_line.version?
                self._request_start_line.version == 'HTTP/1.1' and
                # 304 responses have no body (not even a zero-length body), and so
                # should not have either Content-Length or Transfer-Encoding.
                # headers.
                start_line.code not in (204, 304) and
                # No need to chunk the output if a Content-Length is specified.
                'Content-Length' not in headers and
                # Applications are discouraged from touching Transfer-Encoding,
                # but if they do, leave it alone.
                'Transfer-Encoding' not in headers)
            # If a 1.0 client asked for keep-alive, add the header.
            if (self._request_start_line.version == 'HTTP/1.0' and
                (self._request_headers.get('Connection', '').lower() ==
                 'keep-alive')):
                headers['Connection'] = 'Keep-Alive'
        if self._chunking_output:
            headers['Transfer-Encoding'] = 'chunked'
        if (not self.is_client and
            (self._request_start_line.method == 'HEAD' or
             start_line.code == 304)):
            self._expected_content_remaining = 0
        elif 'Content-Length' in headers:
            self._expected_content_remaining = int(headers['Content-Length'])
        else:
            self._expected_content_remaining = None
        # TODO: headers are supposed to be of type str, but we still have some
        # cases that let bytes slip through. Remove these native_str calls when those
        # are fixed.
        header_lines = (native_str(n) + ": " + native_str(v) for n, v in headers.get_all())
        if PY3:
            lines.extend(l.encode('latin1') for l in header_lines)
        else:
            lines.extend(header_lines)
        for line in lines:
            if b'\n' in line:
                raise ValueError('Newline in header: ' + repr(line))
        future = None
        if self.stream.closed():
            future = self._write_future = Future()
            future.set_exception(iostream.StreamClosedError())
            future.exception()
        else:
            if callback is not None:
                self._write_callback = stack_context.wrap(callback)
            else:
                future = self._write_future = Future()
            data = b"\r\n".join(lines) + b"\r\n\r\n"
            if chunk:
                data += self._format_chunk(chunk)
            self._pending_write = self.stream.write(data)
            self._pending_write.add_done_callback(self._on_write_complete)
        return future

    def _format_chunk(self, chunk):
        if self._expected_content_remaining is not None:
            self._expected_content_remaining -= len(chunk)
            if self._expected_content_remaining < 0:
                # Close the stream now to stop further framing errors.
                self.stream.close()
                raise httputil.HTTPOutputError(
                    "Tried to write more data than Content-Length")
        if self._chunking_output and chunk:
            # Don't write out empty chunks because that means END-OF-STREAM
            # with chunked encoding
            return utf8("%x" % len(chunk)) + b"\r\n" + chunk + b"\r\n"
        else:
            return chunk

    def write(self, chunk, callback=None):
        """Implements `.HTTPConnection.write`.

        For backwards compatibility is is allowed but deprecated to
        skip `write_headers` and instead call `write()` with a
        pre-encoded header block.
        """
        future = None
        if self.stream.closed():
            future = self._write_future = Future()
            self._write_future.set_exception(iostream.StreamClosedError())
            self._write_future.exception()
        else:
            if callback is not None:
                self._write_callback = stack_context.wrap(callback)
            else:
                future = self._write_future = Future()
            self._pending_write = self.stream.write(self._format_chunk(chunk))
            self._pending_write.add_done_callback(self._on_write_complete)
        return future

    def finish(self):
        """Implements `.HTTPConnection.finish`."""
        if (self._expected_content_remaining is not None and
                self._expected_content_remaining != 0 and
                not self.stream.closed()):
            self.stream.close()
            raise httputil.HTTPOutputError(
                "Tried to write %d bytes less than Content-Length" %
                self._expected_content_remaining)
        if self._chunking_output:
            if not self.stream.closed():
                self._pending_write = self.stream.write(b"0\r\n\r\n")
                self._pending_write.add_done_callback(self._on_write_complete)
        self._write_finished = True
        # If the app finished the request while we're still reading,
        # divert any remaining data away from the delegate and
        # close the connection when we're done sending our response.
        # Closing the connection is the only way to avoid reading the
        # whole input body.
        if not self._read_finished:
            self._disconnect_on_finish = True
        # No more data is coming, so instruct TCP to send any remaining
        # data immediately instead of waiting for a full packet or ack.
        self.stream.set_nodelay(True)
        if self._pending_write is None:
            self._finish_request(None)
        else:
            self._pending_write.add_done_callback(self._finish_request)

    def _on_write_complete(self, future):
        exc = future.exception()
        if exc is not None and not isinstance(exc, iostream.StreamClosedError):
            future.result()
        if self._write_callback is not None:
            callback = self._write_callback
            self._write_callback = None
            self.stream.io_loop.add_callback(callback)
        if self._write_future is not None:
            future = self._write_future
            self._write_future = None
            future.set_result(None)

    def _can_keep_alive(self, start_line, headers):
        if self.params.no_keep_alive:
            return False
        connection_header = headers.get("Connection")
        if connection_header is not None:
            connection_header = connection_header.lower()
        if start_line.version == "HTTP/1.1":
            return connection_header != "close"
        elif ("Content-Length" in headers or
              headers.get("Transfer-Encoding", "").lower() == "chunked" or
              getattr(start_line, 'method', None) in ("HEAD", "GET")):
            # start_line may be a request or reponse start line; only
            # the former has a method attribute.
            return connection_header == "keep-alive"
        return False

    def _finish_request(self, future):
        self._clear_callbacks()
        if not self.is_client and self._disconnect_on_finish:
            self.close()
            return
        # Turn Nagle's algorithm back on, leaving the stream in its
        # default state for the next request.
        self.stream.set_nodelay(False)
        if not self._finish_future.done():
            self._finish_future.set_result(None)

    def _parse_headers(self, data):
        # The lstrip removes newlines that some implementations sometimes
        # insert between messages of a reused connection.  Per RFC 7230,
        # we SHOULD ignore at least one empty line before the request.
        # http://tools.ietf.org/html/rfc7230#section-3.5
        data = native_str(data.decode('latin1')).lstrip("\r\n")
        # RFC 7230 section allows for both CRLF and bare LF.
        eol = data.find("\n")
        start_line = data[:eol].rstrip("\r")
        try:
            headers = httputil.HTTPHeaders.parse(data[eol:])
        except ValueError:
            # probably form split() if there was no ':' in the line
            raise httputil.HTTPInputError("Malformed HTTP headers: %r" %
                                          data[eol:100])
        return start_line, headers

    def _read_body(self, code, headers, delegate):
        if "Content-Length" in headers:
            if "Transfer-Encoding" in headers:
                # Response cannot contain both Content-Length and
                # Transfer-Encoding headers.
                # http://tools.ietf.org/html/rfc7230#section-3.3.3
                raise httputil.HTTPInputError(
                    "Response with both Transfer-Encoding and Content-Length")
            if "," in 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*', headers["Content-Length"])
                if any(i != pieces[0] for i in pieces):
                    raise httputil.HTTPInputError(
                        "Multiple unequal Content-Lengths: %r" %
                        headers["Content-Length"])
                headers["Content-Length"] = pieces[0]

            try:
                content_length = int(headers["Content-Length"])
            except ValueError:
                # Handles non-integer Content-Length value.
                raise httputil.HTTPInputError(
                    "Only integer Content-Length is allowed: %s" % headers["Content-Length"])

            if content_length > self._max_body_size:
                raise httputil.HTTPInputError("Content-Length too long")
        else:
            content_length = None

        if code == 204:
            # This response code is not allowed to have a non-empty body,
            # and has an implicit length of zero instead of read-until-close.
            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3
            if ("Transfer-Encoding" in headers or
                    content_length not in (None, 0)):
                raise httputil.HTTPInputError(
                    "Response with code %d should not have body" % code)
            content_length = 0

        if content_length is not None:
            return self._read_fixed_body(content_length, delegate)
        if headers.get("Transfer-Encoding") == "chunked":
            return self._read_chunked_body(delegate)
        if self.is_client:
            return self._read_body_until_close(delegate)
        return None

    @gen.coroutine
    def _read_fixed_body(self, content_length, delegate):
        while content_length > 0:
            body = yield self.stream.read_bytes(
                min(self.params.chunk_size, content_length), partial=True)
            content_length -= len(body)
            if not self._write_finished or self.is_client:
                with _ExceptionLoggingContext(app_log):
                    ret = delegate.data_received(body)
                    if ret is not None:
                        yield ret

    @gen.coroutine
    def _read_chunked_body(self, delegate):
        # TODO: "chunk extensions" http://tools.ietf.org/html/rfc2616#section-3.6.1
        total_size = 0
        while True:
            chunk_len = yield self.stream.read_until(b"\r\n", max_bytes=64)
            chunk_len = int(chunk_len.strip(), 16)
            if chunk_len == 0:
                return
            total_size += chunk_len
            if total_size > self._max_body_size:
                raise httputil.HTTPInputError("chunked body too large")
            bytes_to_read = chunk_len
            while bytes_to_read:
                chunk = yield self.stream.read_bytes(
                    min(bytes_to_read, self.params.chunk_size), partial=True)
                bytes_to_read -= len(chunk)
                if not self._write_finished or self.is_client:
                    with _ExceptionLoggingContext(app_log):
                        ret = delegate.data_received(chunk)
                        if ret is not None:
                            yield ret
            # chunk ends with \r\n
            crlf = yield self.stream.read_bytes(2)
            assert crlf == b"\r\n"

    @gen.coroutine
    def _read_body_until_close(self, delegate):
        body = yield self.stream.read_until_close()
        if not self._write_finished or self.is_client:
            with _ExceptionLoggingContext(app_log):
                delegate.data_received(body)


class _GzipMessageDelegate(httputil.HTTPMessageDelegate):
    """Wraps an `HTTPMessageDelegate` to decode ``Content-Encoding: gzip``.
    """
    def __init__(self, delegate, chunk_size):
        self._delegate = delegate
        self._chunk_size = chunk_size
        self._decompressor = None

    def headers_received(self, start_line, headers):
        if headers.get("Content-Encoding") == "gzip":
            self._decompressor = GzipDecompressor()
            # Downstream delegates will only see uncompressed data,
            # so rename the content-encoding header.
            # (but note that curl_httpclient doesn't do this).
            headers.add("X-Consumed-Content-Encoding",
                        headers["Content-Encoding"])
            del headers["Content-Encoding"]
        return self._delegate.headers_received(start_line, headers)

    @gen.coroutine
    def data_received(self, chunk):
        if self._decompressor:
            compressed_data = chunk
            while compressed_data:
                decompressed = self._decompressor.decompress(
                    compressed_data, self._chunk_size)
                if decompressed:
                    ret = self._delegate.data_received(decompressed)
                    if ret is not None:
                        yield ret
                compressed_data = self._decompressor.unconsumed_tail
        else:
            ret = self._delegate.data_received(chunk)
            if ret is not None:
                yield ret

    def finish(self):
        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
                self._delegate.data_received(tail)
        return self._delegate.finish()

    def on_connection_close(self):
        return self._delegate.on_connection_close()


class HTTP1ServerConnection(object):
    """An HTTP/1.x server."""
    def __init__(self, stream, params=None, context=None):
        """
        :arg stream: an `.IOStream`
        :arg params: a `.HTTP1ConnectionParameters` or None
        :arg context: an opaque application-defined object that is accessible
            as ``connection.context``
        """
        self.stream = stream
        if params is None:
            params = HTTP1ConnectionParameters()
        self.params = params
        self.context = context
        self._serving_future = None

    @gen.coroutine
    def close(self):
        """Closes the connection.

        Returns a `.Future` that resolves after the serving loop has exited.
        """
        self.stream.close()
        # Block until the serving loop is done, but ignore any exceptions
        # (start_serving is already responsible for logging them).
        try:
            yield self._serving_future
        except Exception:
            pass

    def start_serving(self, delegate):
        """Starts serving requests on this connection.

        :arg delegate: a `.HTTPServerConnectionDelegate`
        """
        assert isinstance(delegate, httputil.HTTPServerConnectionDelegate)
        self._serving_future = self._server_request_loop(delegate)
        # Register the future on the IOLoop so its errors get logged.
        self.stream.io_loop.add_future(self._serving_future,
                                       lambda f: f.result())

    @gen.coroutine
    def _server_request_loop(self, delegate):
        try:
            while True:
                conn = HTTP1Connection(self.stream, False,
                                       self.params, self.context)
                request_delegate = delegate.start_request(self, conn)
                try:
                    ret = yield conn.read_response(request_delegate)
                except (iostream.StreamClosedError,
                        iostream.UnsatisfiableReadError):
                    return
                except _QuietException:
                    # This exception was already logged.
                    conn.close()
                    return
                except Exception:
                    gen_log.error("Uncaught exception", exc_info=True)
                    conn.close()
                    return
                if not ret:
                    return
                yield gen.moment
        finally:
            delegate.on_close(self)

```
--- 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