From 73a6e89fad1296c1891fc60e01eaadfc56bb5705 Mon Sep 17 00:00:00 2001 From: Marcelo Trylesinski Date: Thu, 3 Feb 2022 13:46:59 +0100 Subject: [PATCH] Revert "fix: move all data handle to protocol & ensure connection is closed (#1332)" This reverts commit fc6e056e628923b0ae41a39f02b8fee8f1fc932e. --- uvicorn/_handlers/http.py | 23 +++++++++++++++-------- uvicorn/protocols/http/h11_impl.py | 4 ---- uvicorn/protocols/http/httptools_impl.py | 2 -- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/uvicorn/_handlers/http.py b/uvicorn/_handlers/http.py index 0d0fc9bab..f70ab708c 100644 --- a/uvicorn/_handlers/http.py +++ b/uvicorn/_handlers/http.py @@ -7,9 +7,6 @@ from uvicorn.server import ServerState -MAX_RECV = 2 ** 16 - - async def handle_http( reader: asyncio.StreamReader, writer: asyncio.StreamWriter, @@ -36,13 +33,13 @@ async def handle_http( # Use a future to coordinate between the protocol and this handler task. # https://docs.python.org/3/library/asyncio-protocol.html#connecting-existing-sockets loop = asyncio.get_event_loop() - reader_read = asyncio.create_task(reader.read(MAX_RECV)) + connection_lost = loop.create_future() # Switch the protocol from the stream reader to our own HTTP protocol class. protocol = config.http_protocol_class( # type: ignore[call-arg, operator] config=config, server_state=server_state, - on_connection_lost=reader_read.cancel, + on_connection_lost=lambda: connection_lost.set_result(True), ) transport = writer.transport transport.set_protocol(protocol) @@ -59,7 +56,7 @@ async def handle_http( @task.add_done_callback def retrieve_exception(task: asyncio.Task) -> None: - exc = task.exception() if not task.cancelled() else None + exc = task.exception() if exc is None: return @@ -77,5 +74,15 @@ def retrieve_exception(task: asyncio.Task) -> None: # Kick off the HTTP protocol. protocol.connection_made(transport) - data = await reader_read - protocol.data_received(data) + + # Pass any data already in the read buffer. + # The assumption here is that we haven't read any data off the stream reader + # yet: all data that the client might have already sent since the connection has + # been established is in the `_buffer`. + data = reader._buffer # type: ignore + if data: + protocol.data_received(data) + + # Let the transport run in the background. When closed, this future will complete + # and we'll exit here. + await connection_lost diff --git a/uvicorn/protocols/http/h11_impl.py b/uvicorn/protocols/http/h11_impl.py index b4f4e1ac9..76af34393 100644 --- a/uvicorn/protocols/http/h11_impl.py +++ b/uvicorn/protocols/http/h11_impl.py @@ -222,10 +222,6 @@ def handle_events(self): continue self.cycle.more_body = False self.cycle.message_event.set() - elif event_type is h11.ConnectionClosed: - break - if self.conn.our_state is h11.MUST_CLOSE and not self.transport.is_closing(): - self.transport.close() def handle_upgrade(self, event): upgrade_value = None diff --git a/uvicorn/protocols/http/httptools_impl.py b/uvicorn/protocols/http/httptools_impl.py index bac061771..34f66c97c 100644 --- a/uvicorn/protocols/http/httptools_impl.py +++ b/uvicorn/protocols/http/httptools_impl.py @@ -136,8 +136,6 @@ def data_received(self, data): self.transport.close() except httptools.HttpParserUpgrade: self.handle_upgrade() - if data == b"" and not self.transport.is_closing(): - self.transport.close() def handle_upgrade(self): upgrade_value = None