From e375de0f33cd644c0976045d234f7a45d327fe6a Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Wed, 25 Apr 2018 15:00:43 +0200 Subject: [PATCH] [internal.http.request.parser.header] multi-value header parser --- internal/http/request/parser/header/public.go | 51 +++++++++++++++++++ internal/http/request/parser/header/types.go | 22 ++++++++ 2 files changed, 73 insertions(+) create mode 100644 internal/http/request/parser/header/public.go create mode 100644 internal/http/request/parser/header/types.go diff --git a/internal/http/request/parser/header/public.go b/internal/http/request/parser/header/public.go new file mode 100644 index 0000000..36be125 --- /dev/null +++ b/internal/http/request/parser/header/public.go @@ -0,0 +1,51 @@ +package header + +import ( + "regexp" + "fmt" + "strings" + "bytes" +) + +// parse tries to return a 'T' (httpHeader) from a byte array +func Parse(b []byte) (*T, error) { + + /* (1) Split by ':' */ + parts := bytes.Split(b, []byte(": ")) + + if len(parts) != 2 { + return nil, fmt.Errorf("Invalid HTTP header format '%s'", b) + } + + /* (2) Create instance */ + inst := new(T) + + /* (3) Check for header name */ + switch strings.ToLower(string(parts[0])) { + case "host": inst.Name = HOST + case "upgrade": inst.Name = UPGRADE + case "connection": inst.Name = CONNECTION + case "origin": inst.Name = ORIGIN + case "sec-websocket-key": inst.Name = WSKEY + case "sec-websocket-protocol": inst.Name = WSPROTOCOL + case "sec-websocket-extensions": inst.Name = WSEXTENSIONS + case "sec-websocket-version": inst.Name = WSVERSION + default: inst.Name = UNKNOWN + } + + /* (4) Check format */ + checker := regexp.MustCompile(`^(?:[^,]+,\s*)*[^,]+$`) + if !checker.Match(parts[1]) { + return nil, fmt.Errorf("Invalid HTTP header value format '%s'", parts[1]); + } + + /* (5) Normalise format */ + normaliser := regexp.MustCompile(`,\s+`) + values := normaliser.ReplaceAll(parts[1], []byte(",")) + + /* (5) Split values */ + inst.Values = bytes.Split(values, []byte(",")) + + return inst, nil + +} \ No newline at end of file diff --git a/internal/http/request/parser/header/types.go b/internal/http/request/parser/header/types.go new file mode 100644 index 0000000..e72c27e --- /dev/null +++ b/internal/http/request/parser/header/types.go @@ -0,0 +1,22 @@ +package header + +// HeaderType represents all 'valid' HTTP request headers +type HeaderType byte +const ( + UNKNOWN HeaderType = iota + HOST + UPGRADE + CONNECTION + ORIGIN + WSKEY + WSPROTOCOL + WSEXTENSIONS + WSVERSION +) + + +// T represents the data of a HTTP request header +type T struct{ + Name HeaderType + Values [][]byte +} \ No newline at end of file