2021-05-14 15:19:02 +00:00
|
|
|
package upgrade
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
// HeaderType represents all 'valid' HTTP request headers
|
|
|
|
type HeaderType uint8
|
|
|
|
|
|
|
|
// header types
|
|
|
|
const (
|
|
|
|
Unknown HeaderType = iota
|
|
|
|
Host
|
|
|
|
Upgrade
|
|
|
|
Connection
|
|
|
|
Origin
|
|
|
|
WSKey
|
|
|
|
WSProtocol
|
|
|
|
WSExtensions
|
|
|
|
WSVersion
|
|
|
|
)
|
|
|
|
|
|
|
|
// HeaderValue represents a unique or multiple header value(s)
|
|
|
|
type HeaderValue [][]byte
|
|
|
|
|
|
|
|
// Header represents the data of a HTTP request header
|
|
|
|
type Header struct {
|
|
|
|
Name HeaderType
|
|
|
|
Values HeaderValue
|
|
|
|
}
|
|
|
|
|
|
|
|
// ReadHeader tries to parse an HTTP header from a byte array
|
|
|
|
func ReadHeader(b []byte) (*Header, error) {
|
|
|
|
|
|
|
|
// 1. Split by ':'
|
|
|
|
parts := bytes.Split(b, []byte(": "))
|
|
|
|
|
|
|
|
if len(parts) != 2 {
|
2021-06-15 20:13:36 +00:00
|
|
|
return nil, fmt.Errorf("invalid HTTP header format '%s'", b)
|
2021-05-14 15:19:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 2. Create instance
|
|
|
|
inst := &Header{}
|
|
|
|
|
|
|
|
// 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. Split values
|
|
|
|
inst.Values = bytes.Split(parts[1], []byte(", "))
|
|
|
|
|
|
|
|
return inst, nil
|
|
|
|
|
|
|
|
}
|