threading implementation with `process_request` raise ConnectionClosedError
Flowrey opened this issue · comments
I'm using:
- Python: 3.12
- websockets: 12.0
When using the threading implementation like in this code:
import http
from websockets.sync.server import serve, ServerConnection, Request, Response
from websockets.http11 import datastructures
def health_check(websocket: ServerConnection, request: Request):
if request.path == "/healthz":
return Response(http.HTTPStatus.OK, "OK", datastructures.Headers([]), b"OK")
else:
return None
def echo(websocket):
for message in websocket:
websocket.send(message)
def main():
with serve(echo, "localhost", 8765, process_request=health_check) as server:
server.serve_forever()
main()
Any call to the /healthz endpoint works but raise a ConnectionCloseError
:
connection handler failed
Traceback (most recent call last):
File "/home/flowrey/Code/poc/venv/lib64/python3.12/site-packages/websockets/sync/server.py", line 499, in conn_handler
handler(connection)
File "/home/flowrey/Code/poc/server.py", line 13, in echo
for message in websocket:
File "/home/flowrey/Code/poc/venv/lib64/python3.12/site-packages/websockets/sync/connection.py", line 162, in __iter__
yield self.recv()
^^^^^^^^^^^
File "/home/flowrey/Code/poc/venv/lib64/python3.12/site-packages/websockets/sync/connection.py", line 201, in recv
raise self.protocol.close_exc from self.recv_events_exc
websockets.exceptions.ConnectionClosedError: no close frame received or sent
I noticed that it is receiving empty bytes as a data response, and this causes the socket to close.
websockets/src/websockets/sync/connection.py
Lines 549 to 550 in e217458
websockets/src/websockets/sync/connection.py
Lines 614 to 616 in e217458
Another thing is that when the status code is not 101, the state does not end up being OPEN, which then closes the connection as well.
websockets/src/websockets/server.py
Lines 541 to 547 in e217458
websockets/src/websockets/sync/server.py
Lines 143 to 146 in e217458
I have made this PR that solved this error for me, but I don't know if it broke tests or other functinalities
#1440
The change causes tests to hang -- because you removed the code paths that manages the end of a connection.
The issue looks legit but that's not the right fix.
I think I figured it out now. The code is handling all connections as WebSocket connections. When it is an HTTP connection and a request is made, it is supposed to close the connection, which differs from a WebSocket, where it is expected to keep the connection alive. I created a checker to verify if it is a WebSocket before handling it.
I have created this new PR with this change:
#1443