瀏覽代碼

Compare request header tokens with ASCII case folding

Compare request header tokens with ASCII case folding per the WebSocket
RFC.
Gary Burd 8 年之前
父節點
當前提交
447c2df769
共有 2 個文件被更改,包括 44 次插入2 次删除
  1. 26 2
      util.go
  2. 18 0
      util_test.go

+ 26 - 2
util.go

@@ -11,6 +11,7 @@ import (
 	"io"
 	"net/http"
 	"strings"
+	"unicode/utf8"
 )
 
 var keyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
@@ -127,8 +128,31 @@ func nextTokenOrQuoted(s string) (value string, rest string) {
 	return "", ""
 }
 
+// equalASCIIFold returns true if s is equal to t with ASCII case folding.
+func equalASCIIFold(s, t string) bool {
+	for s != "" && t != "" {
+		sr, size := utf8.DecodeRuneInString(s)
+		s = s[size:]
+		tr, size := utf8.DecodeRuneInString(t)
+		t = t[size:]
+		if sr == tr {
+			continue
+		}
+		if 'A' <= sr && sr <= 'Z' {
+			sr = sr + 'a' - 'A'
+		}
+		if 'A' <= tr && tr <= 'Z' {
+			tr = tr + 'a' - 'A'
+		}
+		if sr != tr {
+			return false
+		}
+	}
+	return s == t
+}
+
 // tokenListContainsValue returns true if the 1#token header with the given
-// name contains token.
+// name contains a token equal to value with ASCII case folding.
 func tokenListContainsValue(header http.Header, name string, value string) bool {
 headers:
 	for _, s := range header[name] {
@@ -142,7 +166,7 @@ headers:
 			if s != "" && s[0] != ',' {
 				continue headers
 			}
-			if strings.EqualFold(t, value) {
+			if equalASCIIFold(t, value) {
 				return true
 			}
 			if s == "" {

+ 18 - 0
util_test.go

@@ -10,6 +10,24 @@ import (
 	"testing"
 )
 
+var equalASCIIFoldTests = []struct {
+	t, s string
+	eq   bool
+}{
+	{"WebSocket", "websocket", true},
+	{"websocket", "WebSocket", true},
+	{"Öyster", "öyster", false},
+}
+
+func TestEqualASCIIFold(t *testing.T) {
+	for _, tt := range equalASCIIFoldTests {
+		eq := equalASCIIFold(tt.s, tt.t)
+		if eq != tt.eq {
+			t.Errorf("equalASCIIFold(%q, %q) = %v, want %v", tt.s, tt.t, eq, tt.eq)
+		}
+	}
+}
+
 var tokenListContainsValueTests = []struct {
 	value string
 	ok    bool