Skip to content

Commit cd992f8

Browse files
provinzkrautpgjones
authored andcommitted
fix connection state leak
1 parent 50057c4 commit cd992f8

File tree

5 files changed

+47
-4
lines changed

5 files changed

+47
-4
lines changed

src/hypercorn/asyncio/tcp_server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ async def run(self) -> None:
6161
self.config,
6262
self.context,
6363
task_group,
64-
ConnectionState(self.state.copy()),
64+
ConnectionState(self.state),
6565
ssl,
6666
client,
6767
server,

src/hypercorn/protocol/http_stream.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ async def handle(self, event: Event) -> None:
9797
"headers": event.headers,
9898
"client": self.client,
9999
"server": self.server,
100-
"state": event.state,
100+
"state": event.state.copy(),
101101
"extensions": {},
102102
}
103103

src/hypercorn/protocol/ws_stream.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ async def handle(self, event: Event) -> None:
219219
"headers": event.headers,
220220
"client": self.client,
221221
"server": self.server,
222-
"state": event.state,
222+
"state": event.state.copy(),
223223
"subprotocols": self.handshake.subprotocols or [],
224224
"extensions": {"websocket.http.response": {}},
225225
}

src/hypercorn/trio/tcp_server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ async def run(self) -> None:
6464
self.config,
6565
self.context,
6666
task_group,
67-
ConnectionState(self.state.copy()),
67+
ConnectionState(self.state),
6868
ssl,
6969
client,
7070
server,

tests/e2e/test_httpx.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,46 @@ async def serve() -> None:
5555
result.raise_for_status()
5656

5757
shutdown.set()
58+
59+
60+
@pytest.mark.trio
61+
async def test_handle_isolate_state():
62+
config = Config()
63+
config.bind = ["0.0.0.0:1234"]
64+
config.accesslog = "-" # Log to stdout/err
65+
config.errorlog = "-"
66+
67+
async def app(scope, receive, send):
68+
assert scope["type"] == "http"
69+
70+
await send(
71+
{
72+
"type": "http.response.start",
73+
"status": 200,
74+
"headers": [[b"content-type", b"text/plain"]],
75+
}
76+
)
77+
await send(
78+
{"type": "http.response.body", "body": scope["state"].get("key", b"")}
79+
)
80+
scope["state"]["key"] = b"one"
81+
82+
async with trio.open_nursery() as nursery:
83+
shutdown = trio.Event()
84+
85+
async def serve() -> None:
86+
await hypercorn.trio.serve(app, config, shutdown_trigger=shutdown.wait)
87+
88+
nursery.start_soon(serve)
89+
90+
await trio.testing.wait_all_tasks_blocked()
91+
92+
client = httpx.AsyncClient()
93+
94+
result = await client.get("http://0.0.0.0:1234/")
95+
assert result.content == b""
96+
97+
result = await client.get("http://0.0.0.0:1234/")
98+
assert result.content == b""
99+
100+
shutdown.set()

0 commit comments

Comments
 (0)