-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Strange WebSocket behavior since version 3.7 #5180
Comments
@asvetlov async def test_ws_close_return_code(aiohttp_client) -> None:
async def handler(request):
ws = web.WebSocketResponse()
await ws.prepare(request)
await ws.close()
return ws
app = web.Application()
app.router.add_route("GET", "/", handler)
client = await aiohttp_client(app)
resp = await client.ws_connect("/")
await resp.send_str('some data')
await asyncio.sleep(0.1)
await resp.receive()
assert resp.close_code == WSCloseCode.OK In async def close(self, *, code: int = 1000, message: bytes = b"") -> bool:
# we need to break `receive()` cycle first,
# `close()` may be called from different task
if self._waiting is not None and not self._closed:
self._reader.feed_data(WS_CLOSING_MESSAGE, 0)
await self._waiting
if not self._closed:
self._cancel_heartbeat()
self._closed = True
try:
await self._writer.close(code, message)
except asyncio.CancelledError:
self._close_code = 1006
self._response.close()
raise
except Exception as exc: # <-- we come to this branch due to ConnectionResetError("Cannot write to closing transport") from WebSocketWriter
self._close_code = 1006
self._exception = exc
self._response.close()
return True This overwrites the OK close code. The real reason IMHO in overcomplicated (closing/closed boolean flags) logic of closing the ws. I would recommend to refactor it using finite state machine. |
Timing issue? |
Reread you message again. Looks like your detection is right. Please let me keep the issue open for a while |
WS client received the close message from the server and set the code to 1000. |
@asvetlov any thoughts on this? |
WebSocket problems are on my radar but I have no capacity to analyze them right now. |
@bdraco Fancy another websocket one? Test is in #5180 (comment) Issue here is the client receives a Close frame, then tries to send a Close frame in response, but then hits this error:
This suggests the server has closed the connection prematurely. The server should wait for the Close frame from the client before closing the connection: https://datatracker.ietf.org/doc/html/rfc6455#section-1.4 |
I’ll put it in my queue. Busy this week though so probably next weekend before I look |
Note to self: Need to make sure we don't wait too long for a close frame that never comes as well. Probably needs a timeout for that if we don't already have one |
This is a followup to add more coverage for #5180
It took me a while but I realized that this is behaving as expected because the client is sending a string |
Hmm, I suppose that's a bit of an odd case. close() could maybe drain the buffer or something, but shouldn't really be happening in real use cases regardless. |
Close code of WebSocket became different after upgrading aiohttp from version 3.6.3 to version 3.7.2.
server.py:
Server logs are the same for all versions of aiohttp.
client.py:
Client logs (aiohttp==3.6.3):
Client logs (aiohttp==3.7.2):
The text was updated successfully, but these errors were encountered: