Skip to content

Commit 873e67e

Browse files
authored
Fix how the client checks for presence of Upgrade: websocket, Connection: upgrade (#604)
The values of the `Upgrade` and `Connection` response headers can contain multiple tokens, for example Connection: upgrade, keep-alive The WebSocket RFC describes the checking of these as follows: 2. If the response lacks an |Upgrade| header field or the |Upgrade| header field contains a value that is not an ASCII case- insensitive match for the value "websocket", the client MUST _Fail the WebSocket Connection_. 3. If the response lacks a |Connection| header field or the |Connection| header field doesn't contain a token that is an ASCII case-insensitive match for the value "Upgrade", the client MUST _Fail the WebSocket Connection_. It is careful to note "contains a value", "contains a token". Previously, the client would reject with "bad handshake" if the header doesn't contain exactly the value it looks for. Change the checks to use `tokenListContainsValue` instead, which is incidentally what the server is already doing for similar checks.
1 parent b65e629 commit 873e67e

File tree

2 files changed

+19
-2
lines changed

2 files changed

+19
-2
lines changed

client.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,8 +348,8 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
348348
}
349349

350350
if resp.StatusCode != 101 ||
351-
!strings.EqualFold(resp.Header.Get("Upgrade"), "websocket") ||
352-
!strings.EqualFold(resp.Header.Get("Connection"), "upgrade") ||
351+
!tokenListContainsValue(resp.Header, "Upgrade", "websocket") ||
352+
!tokenListContainsValue(resp.Header, "Connection", "upgrade") ||
353353
resp.Header.Get("Sec-Websocket-Accept") != computeAcceptKey(challengeKey) {
354354
// Before closing the network connection on return from this
355355
// function, slurp up some of the response to aid application

client_server_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,23 @@ func TestBadMethod(t *testing.T) {
481481
}
482482
}
483483

484+
func TestDialExtraTokensInRespHeaders(t *testing.T) {
485+
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
486+
challengeKey := r.Header.Get("Sec-Websocket-Key")
487+
w.Header().Set("Upgrade", "foo, websocket")
488+
w.Header().Set("Connection", "upgrade, keep-alive")
489+
w.Header().Set("Sec-Websocket-Accept", computeAcceptKey(challengeKey))
490+
w.WriteHeader(101)
491+
}))
492+
defer s.Close()
493+
494+
ws, _, err := cstDialer.Dial(makeWsProto(s.URL), nil)
495+
if err != nil {
496+
t.Fatalf("Dial: %v", err)
497+
}
498+
defer ws.Close()
499+
}
500+
484501
func TestHandshake(t *testing.T) {
485502
s := newServer(t)
486503
defer s.Close()

0 commit comments

Comments
 (0)