Skip to content

Commit 447c2df

Browse files
committed
Compare request header tokens with ASCII case folding
Compare request header tokens with ASCII case folding per the WebSocket RFC.
1 parent aa5ed01 commit 447c2df

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

util.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"io"
1212
"net/http"
1313
"strings"
14+
"unicode/utf8"
1415
)
1516

1617
var keyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
@@ -127,8 +128,31 @@ func nextTokenOrQuoted(s string) (value string, rest string) {
127128
return "", ""
128129
}
129130

131+
// equalASCIIFold returns true if s is equal to t with ASCII case folding.
132+
func equalASCIIFold(s, t string) bool {
133+
for s != "" && t != "" {
134+
sr, size := utf8.DecodeRuneInString(s)
135+
s = s[size:]
136+
tr, size := utf8.DecodeRuneInString(t)
137+
t = t[size:]
138+
if sr == tr {
139+
continue
140+
}
141+
if 'A' <= sr && sr <= 'Z' {
142+
sr = sr + 'a' - 'A'
143+
}
144+
if 'A' <= tr && tr <= 'Z' {
145+
tr = tr + 'a' - 'A'
146+
}
147+
if sr != tr {
148+
return false
149+
}
150+
}
151+
return s == t
152+
}
153+
130154
// tokenListContainsValue returns true if the 1#token header with the given
131-
// name contains token.
155+
// name contains a token equal to value with ASCII case folding.
132156
func tokenListContainsValue(header http.Header, name string, value string) bool {
133157
headers:
134158
for _, s := range header[name] {
@@ -142,7 +166,7 @@ headers:
142166
if s != "" && s[0] != ',' {
143167
continue headers
144168
}
145-
if strings.EqualFold(t, value) {
169+
if equalASCIIFold(t, value) {
146170
return true
147171
}
148172
if s == "" {

util_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,24 @@ import (
1010
"testing"
1111
)
1212

13+
var equalASCIIFoldTests = []struct {
14+
t, s string
15+
eq bool
16+
}{
17+
{"WebSocket", "websocket", true},
18+
{"websocket", "WebSocket", true},
19+
{"Öyster", "öyster", false},
20+
}
21+
22+
func TestEqualASCIIFold(t *testing.T) {
23+
for _, tt := range equalASCIIFoldTests {
24+
eq := equalASCIIFold(tt.s, tt.t)
25+
if eq != tt.eq {
26+
t.Errorf("equalASCIIFold(%q, %q) = %v, want %v", tt.s, tt.t, eq, tt.eq)
27+
}
28+
}
29+
}
30+
1331
var tokenListContainsValueTests = []struct {
1432
value string
1533
ok bool

0 commit comments

Comments
 (0)