From c1f354a01ce0384149bebc1874e483c25881ed79 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Fri, 27 May 2016 16:36:28 +0500 Subject: [PATCH] Support lower case headers --- proto/proto.go | 82 ++++++++++++++++++++++++++++++++++++++++++++- proto/proto_test.go | 13 +++++++ 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/proto/proto.go b/proto/proto.go index ad7fe74..314e190 100644 --- a/proto/proto.go +++ b/proto/proto.go @@ -41,11 +41,91 @@ func MIMEHeadersStartPos(payload []byte) int { return bytes.Index(payload, CLRF) + 2 // Find first line end } + +func isLower(b byte) bool { + if 'a' <= b && b <= 'z' { + return true + } + + return false +} + +func toUpper(b byte) byte { + if 'a' <= b && b <= 'z' { + b -= 'a' - 'A' + } + return b +} + +func toLower(b byte) byte { + if 'A' <= b && b <= 'Z' { + b += 'a' - 'A' + } + return b +} + +func headerIndex(payload []byte, name []byte) int { + isLower := isLower(name[0]) + i := 0 + + for { + if i >= len(payload) { + return -1 + } + + if payload[i] == '\n' { + i++ + + // We are at the end + if i == len(payload) { + return -1 + } + + if payload[i] == name[0] || + (!isLower && payload[i] == toLower(name[0])) || + ( isLower && payload[i] == toUpper(name[0])) { + + i++ + j := 1 + for { + if j == len(name) { + // Matched, and return start of the header + return i - len(name) + } + + if payload[i] != name[j] { + break + } + + // If compound header name do one more case check: Content-Length or Transfer-Encoding + if name[j] == '-' { + i++ + j++ + + if !(payload[i] == name[j] || + (!isLower && payload[i] == toLower(name[j])) || + ( isLower && payload[i] == toUpper(name[j]))) { + break + } + } + + j++ + i++ + } + } + } + + i++ + } + + return -1 +} + // header return value and positions of header/value start/end. // If not found, value will be blank, and headerStart will be -1 // Do not support multi-line headers. func header(payload []byte, name []byte) (value []byte, headerStart, valueStart, headerEnd int) { - headerStart = bytes.Index(payload, name) + headerStart = headerIndex(payload, name) if headerStart == -1 { return diff --git a/proto/proto_test.go b/proto/proto_test.go index c489a4e..a8d9179 100644 --- a/proto/proto_test.go +++ b/proto/proto_test.go @@ -41,6 +41,19 @@ func TestHeader(t *testing.T) { if _, headerStart, _, _ = header(payload, []byte("Not-Found")); headerStart != -1 { t.Error("Should not found header") } + + // Lower case headers + payload = []byte("POST /post HTTP/1.1\r\ncontent-length: 7\r\nHost: www.w3.org\r\n\r\na=1&b=2") + + if val = Header(payload, []byte("Content-Length")); !bytes.Equal(val, []byte("7")) { + t.Error("Should find lower case 2 word header") + } + + payload = []byte("POST /post HTTP/1.1\r\ncontent-length: 7\r\nhost: www.w3.org\r\n\r\na=1&b=2") + + if val = Header(payload, []byte("host")); !bytes.Equal(val, []byte("www.w3.org")) { + t.Error("Should find lower case 1 word header") + } } func TestMIMEHeadersEndPos(t *testing.T) {