Skip to content

subprotocol handling appears to differ from WebSocket RFC #1027

@phoddie

Description

@phoddie

This library is used by the Pebble watch project for its pypkjs phone emulation environment. In exploring its subprotocol support, I found that connections fail with Invalid subprotocol if none of the requested subprotocols are returned by the server. The relevant code in this library appears to be the following:

if subprotocols:
subproto = headers.get("sec-websocket-protocol", None)
if not subproto or subproto.lower() not in [s.lower() for s in subprotocols]:
error(f"Invalid subprotocol: {subprotocols}")
return False, None

This project's documentation helpfully links to the WebSocket RFC to explain its behavior. The link is to a non-normative section which states:

The client can request that the server use a specific subprotocol by including the |Sec-WebSocket-Protocol| field in its handshake. If it is specified, the server needs to include the same field and one of the selected subprotocol values in its response for the connection to be established.

This strongly suggests that the server must include one of the subprotocols in its response for the connection to be valid. This is what this library implements.

Unfortunately, the normative text that follows later in the RFC makes it clear that the server may choose not to include any subprotocol in its response and the connection is still valid. For example, it says that if no subprotocol is in the response, the subprotocol is null:

The Subprotocol In Use is defined to be the value of the Sec-WebSocket-Protocol header field in the server's handshake or the null value if that header field was not present in the server's handshake.

It also states that the value provided by the server (or absence thereof) is for scripts (not the WebSocket library) to check which protocol was selected by the server.

The Sec-WebSocket-Protocol header field is used in the WebSocket opening handshake. It is sent from the client to the server and back from the server to the client to confirm the subprotocol of the connection. This enables scripts to both select a subprotocol and be sure that the server agreed to serve that subprotocol.

As far as I am aware, the WebSocket class implementations in all web browsers follow the normative section of the RFC for subprotocols, and so do not reject the handshake if the server does not select any of the requested subprotocols.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions