python-websockets / websockets

Library for building WebSocket servers and clients in Python
https://websockets.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
5.07k stars 506 forks source link

Behaviour of websockets sansI/O Layer when the connection fails #1397

Closed gourav-kandoria closed 10 months ago

gourav-kandoria commented 10 months ago

When the data is received using below method: self.conn.receive_data(data) There are some scenarios(like the size of msg received is more that configured, data received not correct according to websockets specs) where the connections fails, in this scenario, What if there is some exception like ConnectionFailedException which can be thrown when the connection fails. so that appropriate next step can be taken.

For example, something like this

try
    self.conn.receive_data(data)
except ConnectionFailException:
    output = self.conn.data_to_send()
    self.transport.writelines(output)
    self.transport.close()
    # have access to a close code here
    # which can be sent to asgi app in disconnect event
aaugustin commented 10 months ago

receive_data doesn't raise exceptions (other than EOFError if you called receive_eof before, which would be a bug.)

If you give websockets invalid inputs, websockets will close the connection, which you will see because data_to_send will contain the end-of-stream marker b"".

If you want to tell what happened, check the close_exc attribute.

The implementation is designed like this because it's usually a background task/thread reading from the socket and feeding data to websockets with receive_data and there's no convenient way to surface exceptions from there.

aaugustin commented 10 months ago

To illustrate this, the threading-based implementation in websockets (which runs on top of the Sans-I/O layer) calls receive_data without handling exceptions here: https://github.com/python-websockets/websockets/blob/adfb8d69a7a1f6f4c8381c9e7182619d202c3cf2/src/websockets/sync/connection.py#L556

I'm not THAT confident in my ability to write such complex code correctly so I have a catch-all exception handler - https://github.com/python-websockets/websockets/blob/adfb8d69a7a1f6f4c8381c9e7182619d202c3cf2/src/websockets/sync/connection.py#L608-L609 - but I don't expect it to run.