miguelgrinberg / flask-sock

Modern WebSocket support for Flask.
MIT License
272 stars 24 forks source link

ConnectionError() / Invalid frame header when using debug #70

Closed ror3d closed 10 months ago

ror3d commented 11 months ago

I am trying this extension and I am getting an error when running the flask app with the debug webserver.

A minimum example is:

from flask import Flask
from flask_sock import Sock

app = Flask(__name__)
sock = Sock(app)

@sock.route("/test")
def test(ws):
    import time
    while ws.connected:
        ws.send({"data": "test"})
        time.sleep(2)

If I run the app like flask --app app run --debug, and connect to it from the browser with something like

ws = new WebSocket("ws://127.0.0.1:5000/test")
ws.onmessage = function(e){ console.log(e.data); }

It will send the data every 2 seconds as expected, but once I call

ws.close()

on the browser, the server will raise a ConnectionError with the trace:

127.0.0.1 - - [09/Sep/2023 23:09:58] "GET /test HTTP/1.1" 500 -
Traceback (most recent call last):
  File "...\Lib\site-packages\flask\app.py", line 2213, in __call__
    return self.wsgi_app(environ, start_response)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\Lib\site-packages\flask\app.py", line 2197, in wsgi_app
    return response(environ, start_response)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\Lib\site-packages\flask_sock\__init__.py", line 86, in __call__
    raise ConnectionError()

and the browser will get an error like:

WebSocket connection to 'ws://127.0.0.1:5000/test' failed: Invalid frame header

This does not happen when running the server without the --debug option.

miguelgrinberg commented 11 months ago

It has been challenging to get Flask and Werkzeug to work, I have fixed several issues that triggered errors during disconnection, but somehow I have missed this one. I don't know if I'll be able to make it work without breaking other use cases.

ror3d commented 11 months ago

Yeah I think it's fine if it can't be fixed, it's not something that breaks much to be honest, it doesn't seem to cause any crash or anything (although I don't know if behind the scenes it leaves some weird state that could break things later).

But it's good to have it documented so others stumbling into it know that it's happening because the debug flag.

gbrault commented 10 months ago

I have the same issue as well, but no error in the browser. And dispite this, the ws is working. If I am not in debug I get:

2023-09-13 06:53:56,603:ERROR:werkzeug:172.18.0.9 - - [13/Sep/2023 06:53:56] code 400, message Bad request syntax ('\x88\x82@\x06\x05PCî')

My code for ws is looking for an incoming connection and depending on some state variable decide to close access or to continue and use the ws channel.

miguelgrinberg commented 10 months ago

@gbrault I'm not sure what made you think your issue is the same as the one reported here. I really do not see anything in common. Please write a new issue and include code to help me reproduce the issue.

maquak commented 10 months ago

What browser are you using for testing? I was just debugging similar issue and it turns out that Chromium-based browsers would just silently close unsecured localhost WebSockets connection. It worked fine when I tried Safari on macOS.

ror3d commented 10 months ago

What browser are you using for testing? I was just debugging similar issue and it turns out that Chromium-based browsers would just silently close unsecured localhost WebSockets connection. It worked fine when I tried Safari on macOS.

Are you asking me? I think the reproduction steps make it clear that this is not the browser closing the connection automatically, but the server throwing an error when I try to close the connection manually from the browser, but if there is something unclear please let me know so I can improve the bug description.

gbrault commented 10 months ago

All the browser I used got the same result: Firefox, Chrome and Edge. But I just remarked that the dev version I run on my computer works fine (no error whatever) and it's only the Linux version which provides this issue

miguelgrinberg commented 10 months ago

@gbrault I think saying this is a Linux vs Windows problem is a mistake. You have different versions of Flask and Werkzeug on your Linux and Windows machines and that explains the different behaviors.

This problem occurs because Werkzeug (Flask's development web server) is not designed to manage a WebSocket connection. I have attempted to install some hacks that prevent the error during disconnection, and this appears to work on some versions, but not on others.

At the end of the day, Werkzeug is a development web server, so I do not consider this a critical issue. For your production deployment you wouldn't be using this web server, so this error is something that you only need to put up with while developing.

miguelgrinberg commented 10 months ago

@ror3d would you like to install the main branch of this repo and confirm that you are not getting any more crashes when a client closes the WebSocket? The exit should now be clean for both debug and non-debug. Note that I have only tested Flask 3.0 and Werkzeug 3.0.

ror3d commented 10 months ago

@miguelgrinberg Hi! I can confirm that the connection error no longer appears in the terminal on the server side, although Chrome still reports a Invalid frame header error when the connection is closed from javascript. Firefox doesn't seem to care though. This is not a problem I think, just mentioning it in case it can be relevant for other things.

Thanks for your work!