WebSocket-for-Python icon indicating copy to clipboard operation
WebSocket-for-Python copied to clipboard

How to select sub-protocol? And related sub-protocol spec compliance issue

Open kanaka opened this issue 12 years ago • 4 comments

How do I specify what sub-protocols my application supports? I see that the WebSocketTool upgrade method takes a protocols named parameter but how do I specify that list from my application.

Also, I've noticed a spec compliance issue in the upgrade method (e.g. server/cherrypyserver.py about line 158):

if s in protocols:
    ws_protocols.append(s)

and then later:

if ws_protocols:
    response.headers['Sec-WebSocket-Protocol'] = ', '.join(ws_protocols)

While a client is allowed to specify multiple comma separated sub-protocols in the handshake request, the handshake response must only contain one of those items that the server has selected. See the /subprotocol/ description in the server handshake section: http://tools.ietf.org/html/rfc6455#section-4.2.2

kanaka avatar Oct 11 '12 20:10 kanaka

Indeed ws4py doesn't do anything terribly useful with subprotocols because theye weren't a high priority. The better options would be delegate the filtering to the application itself rather than the current naive approach.

Lawouach avatar Oct 12 '12 07:10 Lawouach

Right, and that's my question. How does the server application do filtering of sub-protocols?

For example, in the cherrypy server example is this line:

cherrypy.tools.websocket = WebSocketTool()

However, the initialization of WebSocketTool doesn't take any parameters such as an ordered priority list of sub-protocols, or a filtering function or anything like that. Does that mean I have to sub-class the WebSocketTool class and override the updrade() method in order to select a protocol when the handshake happens?

kanaka avatar Oct 12 '12 13:10 kanaka

Actually the tool takes a parameter in its upgrade method.

Try something along:

tools.websocket.protocols = ['mychat']

But this may not be sufficient and in the future having a callback for the app would be nicer.

Lawouach avatar Oct 12 '12 13:10 Lawouach

Yeah, that will get me started, but it doesn't allow the server application to select the best option from the list provided by the client. For example, my server supports sub-protocol A and sub-protocol B and prefers sub-protocol A. However, if the client only sends sub-protocol B there is no way to indicate this correctly. If the server set tools.websocket.protocols to ['A', 'B'] since it supports both and the client sends A and B as options that it also suppots, then both A and B will be sent back to the client in violation of the spec.

I think the ideal thing would be if the top level class derived from WebSocket had a method such as received_handshake (or new_connection or something) that is called after the handshake request is parsed but before the handshake response is set. This would allow application and protocol and extension negotiation. Perhaps more importantly it would allow the server application to do origin verification to fully comply CORS security (/origin/ in section 4.2.2 http://tools.ietf.org/html/rfc6455#section-4.2.2).

kanaka avatar Oct 12 '12 14:10 kanaka