WebSocket server responds incorrectly if connection is closed without a status code

Open
#263 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
45/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Stale
Tech stack
python
Domain
networking

Research direction

Start by reproducing the issue with examples/echo_gevent_server.py using the documented browser steps and compare behavior at commit 961c07ce16ce4eedc34ca1fdacd29442870feccc. Trace the server's handling of a client close without a status code. Done means the server no longer sends status code 1005 in its close frame while still handling the connection correctly.

Written by the indexing model from the issue text.

Description

If a client closes a connection without providing a status code, the WebSocket server will respond to the client with a close frame that has an invalid status code of 1005. This will cause some browsers, including Chrome and Safari, to display an error in the console.

Steps to reproduce:

I tested using Python 3.6.9 against commit 961c07ce16ce4eedc34ca1fdacd29442870feccc:

  1. Apply the following diff to examples/echo_gevent_server.py:
diff --git a/example/echo_gevent_server.py b/example/echo_gevent_server.py
index 100a536..3ed19f9 100644
--- a/example/echo_gevent_server.py
+++ b/example/echo_gevent_server.py
@@ -78,7 +78,7 @@ class EchoWebSocketApplication(object):
 
         start_response(status, headers)
 
-        return """<html>
+        response = """<html>
         <head>
         <script type='application/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js'></script>
           <script type='application/javascript'>
@@ -120,6 +120,9 @@ class EchoWebSocketApplication(object):
                  $('#message').val("");
                  return false;
               });
+              $('#disconnect').click(function () {
+                ws.close();
+              });
             });
           </script>
         </head>
@@ -130,11 +133,13 @@ class EchoWebSocketApplication(object):
           <label for='message'>%(username)s: </label><input type='text' id='message' />
           <input id='send' type='submit' value='Send' />
           </form>
+          <button id='disconnect'>Disconnect</button>
         </body>
         </html>
         """ % {'username': "User%d" % random.randint(0, 100),
                'host': self.host,
                'port': self.port}
+        yield response.encode()
 
 if __name__ == '__main__':
     from ws4py import configure_logger

  1. Run python example/echo_gevent_server.py
  2. Open http://127.0.0.1:9000 in Chrome and click the "Disconnect" button
  3. The following error is displayed in the console:
Screenshot 2020-06-01 11 14 20

Notes:

It is correct for the server to internally synthesize the status code 1005 when it receives a close frame for the client with no status code, but this particular status code should never be sent back to the client. From the WebSocket RFC:

1005 is a reserved value and MUST NOT be set as a status code in a Close control frame by an endpoint. It is designated for use in applications expecting a status code to indicate that no status code was actually present.

In our application we worked around the issue on the client side by always setting a status code when closing the connection. See https://github.com/hypothesis/client/pull/1941 for details.

Dominant language
Python
Stars
1.1k
Forks
285
PR merge metrics
No merged PRs in 30d

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Lawouach/WebSocket-for-Python

All issues in Lawouach/WebSocket-for-Python

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.