Skip to content

Commit 309e088

Browse files
Emyrknhooyr
authored andcommitted
Handle multiple sec-websocket-keys
1 parent 3233cb5 commit 309e088

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

accept.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,17 @@ func verifyClientRequest(w http.ResponseWriter, r *http.Request) (errCode int, _
185185
return http.StatusBadRequest, fmt.Errorf("unsupported WebSocket protocol version (only 13 is supported): %q", r.Header.Get("Sec-WebSocket-Version"))
186186
}
187187

188-
websocketSecKey := r.Header.Get("Sec-WebSocket-Key")
189-
// The RFC states to remove any leading or trailing whitespace.
190-
websocketSecKey = strings.TrimSpace(websocketSecKey)
191-
if websocketSecKey == "" {
188+
websocketSecKeys := r.Header.Values("Sec-WebSocket-Key")
189+
if len(websocketSecKeys) == 0 {
192190
return http.StatusBadRequest, errors.New("WebSocket protocol violation: missing Sec-WebSocket-Key")
193191
}
194192

193+
if len(websocketSecKeys) > 1 {
194+
return http.StatusBadRequest, errors.New("WebSocket protocol violation: multiple Sec-WebSocket-Key headers")
195+
}
196+
197+
// The RFC states to remove any leading or trailing whitespace.
198+
websocketSecKey := strings.TrimSpace(websocketSecKeys[0])
195199
if v, err := base64.StdEncoding.DecodeString(websocketSecKey); err != nil || len(v) != 16 {
196200
return http.StatusBadRequest, fmt.Errorf("WebSocket protocol violation: invalid Sec-WebSocket-Key %q, must be a 16 byte base64 encoded string", websocketSecKey)
197201
}

accept_test.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,14 @@ func Test_verifyClientHandshake(t *testing.T) {
185185
},
186186
{
187187
name: "missingWebSocketKey",
188+
h: map[string]string{
189+
"Connection": "Upgrade",
190+
"Upgrade": "websocket",
191+
"Sec-WebSocket-Version": "13",
192+
},
193+
},
194+
{
195+
name: "emptyWebSocketKey",
188196
h: map[string]string{
189197
"Connection": "Upgrade",
190198
"Upgrade": "websocket",
@@ -210,6 +218,18 @@ func Test_verifyClientHandshake(t *testing.T) {
210218
"Sec-WebSocket-Key": "notbase64",
211219
},
212220
},
221+
{
222+
name: "extraWebSocketKey",
223+
h: map[string]string{
224+
"Connection": "Upgrade",
225+
"Upgrade": "websocket",
226+
"Sec-WebSocket-Version": "13",
227+
// Kinda cheeky, but http headers are case-insensitive.
228+
// If 2 sec keys are present, this is a failure condition.
229+
"Sec-WebSocket-Key": xrand.Base64(16),
230+
"sec-webSocket-key": xrand.Base64(16),
231+
},
232+
},
213233
{
214234
name: "badHTTPVersion",
215235
h: map[string]string{
@@ -256,7 +276,7 @@ func Test_verifyClientHandshake(t *testing.T) {
256276
}
257277

258278
for k, v := range tc.h {
259-
r.Header.Set(k, v)
279+
r.Header.Add(k, v)
260280
}
261281

262282
_, err := verifyClientRequest(httptest.NewRecorder(), r)

0 commit comments

Comments
 (0)