Reading — step 1 of 5
Read
Subprotocols & Extensions
RFC 6455 hands you a message pipe — TEXT and BINARY frames — and says nothing about what the bytes mean. Is {"op":1} a chat message? An MQTT packet? A GraphQL subscription event? Both sides must agree, and the handshake has a slot for exactly that agreement.
Subprotocols: negotiating meaning
The client offers a list, in preference order; the server picks exactly one or declines:
Client: Sec-WebSocket-Protocol: chat, superchat, json-rpc
Server: Sec-WebSocket-Protocol: superchat
The rules that matter when you implement this:
- The server's chosen value MUST be one the client offered. If a client sees a subprotocol it never asked for, it MUST fail the connection.
- The server may omit the header entirely — meaning "no subprotocol"; the client then decides whether bare WebSocket is acceptable.
- Names are case-sensitive tokens.
Chatandchatare different protocols. - Which side's preference order wins is your server's policy choice; a common design (and this exercise's rule) is that the server's list is ordered by preference and the first server entry the client also offered wins.
Real names you'll meet: mqtt (IoT brokers over WS), graphql-transport-ws / graphql-ws (GraphQL subscriptions), wamp.2.json (WAMP RPC/pub-sub), plus any private string your application invents — the IANA registry exists but unregistered names are fine and common.
Extensions: negotiating the wire format
A subprotocol layers meaning on top of messages. An extension changes the framing itself — which is why extensions get their own header and their own RSV bits in the frame header:
Client: Sec-WebSocket-Extensions: permessage-deflate
Server: Sec-WebSocket-Extensions: permessage-deflate; client_no_context_takeover
permessage-deflate (RFC 7692) compresses payloads and flags compressed messages with the RSV1 bit — a bit that is a protocol error if no extension negotiated it. That's the deal: RSV bits mean nothing until a handshake gives them meaning. The server can also attach parameters when accepting, as above. A dedicated lesson later in this course implements the compression itself.
Libraries (ws, websockets, gorilla) handle the header plumbing; your job as a server author is the selection policy — which is precisely this lesson's exercise.
Your exercise
Implement the negotiation: first entry of the server's list that also appears in the client's list, else (none). What the grader catches: server preference wins — for a,b,c|c,b,a the expected output is a, not c (walking the client's list first is the classic bug). Matching is case-sensitive: Chat|chat expects (none) — do not .lower() anything. And either side empty means no deal: both |chat and chat| expect (none), so filter out empty strings after splitting ("".split(",") yields [""], which would falsely match another empty entry).
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…