diff --git a/header.go b/header.go index c3f4d081..f4474e72 100644 --- a/header.go +++ b/header.go @@ -3,7 +3,9 @@ package gortsplib import ( "bufio" "fmt" + "net/http" "sort" + "strings" ) const ( @@ -12,6 +14,20 @@ const ( _MAX_HEADER_VALUE_LENGTH = 1024 ) +func normalizeHeaderKey(in string) string { + switch strings.ToLower(in) { + case "rtp-info": + return "RTP-INFO" + + case "www-authenticate": + return "WWW-Authenticate" + + case "cseq": + return "CSeq" + } + return http.CanonicalHeaderKey(in) +} + // Header is a RTSP reader, present in both Requests and Responses. type Header map[string][]string @@ -43,6 +59,7 @@ func readHeader(rb *bufio.Reader) (Header, error) { return nil, err } key += string(byts[:len(byts)-1]) + key = normalizeHeaderKey(key) err = readByteEqual(rb, ' ') if err != nil { diff --git a/header_test.go b/header_test.go index 6299ff11..9a2637c8 100644 --- a/header_test.go +++ b/header_test.go @@ -59,3 +59,40 @@ func TestHeaderWrite(t *testing.T) { }) } } + +var casesHeaderNormalization = []struct { + name string + byts []byte + header Header +}{ + { + "standard", + []byte("Content-type: testing\r\n" + + "Content-length: value\r\n" + + "\r\n"), + Header{ + "Content-Type": []string{"testing"}, + "Content-Length": []string{"value"}, + }, + }, + { + "non-standard", + []byte("Www-Authenticate: value\r\n" + + "Cseq: value\r\n" + + "\r\n"), + Header{ + "WWW-Authenticate": []string{"value"}, + "CSeq": []string{"value"}, + }, + }, +} + +func TestHeaderNormalization(t *testing.T) { + for _, c := range casesHeaderNormalization { + t.Run(c.name, func(t *testing.T) { + req, err := readHeader(bufio.NewReader(bytes.NewBuffer(c.byts))) + require.NoError(t, err) + require.Equal(t, c.header, req) + }) + } +}