mirror of
https://github.com/aler9/gortsplib
synced 2025-10-08 16:40:09 +08:00
102 lines
2.0 KiB
Go
102 lines
2.0 KiB
Go
package gortsplib
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// HeaderAuth is an Authenticate or a WWWW-Authenticate header.
|
|
type HeaderAuth struct {
|
|
Prefix string
|
|
Values map[string]string
|
|
}
|
|
|
|
var regHeaderAuthKeyValue = regexp.MustCompile("^([a-z]+)=(\"(.*?)\"|([a-zA-Z0-9]+))(, *|$)")
|
|
|
|
// ReadHeaderAuth parses an Authenticate or a WWW-Authenticate header.
|
|
func ReadHeaderAuth(v HeaderValue) (*HeaderAuth, error) {
|
|
if len(v) == 0 {
|
|
return nil, fmt.Errorf("value not provided")
|
|
}
|
|
|
|
if len(v) > 1 {
|
|
return nil, fmt.Errorf("value provided multiple times (%v)", v)
|
|
}
|
|
|
|
ha := &HeaderAuth{
|
|
Values: make(map[string]string),
|
|
}
|
|
|
|
v0 := v[0]
|
|
|
|
i := strings.IndexByte(v[0], ' ')
|
|
if i < 0 {
|
|
return nil, fmt.Errorf("unable to find prefix (%s)", v0)
|
|
}
|
|
ha.Prefix, v0 = v0[:i], v0[i+1:]
|
|
|
|
for len(v0) > 0 {
|
|
m := regHeaderAuthKeyValue.FindStringSubmatch(v0)
|
|
if m == nil {
|
|
return nil, fmt.Errorf("unable to parse key-value (%s)", v0)
|
|
}
|
|
v0 = v0[len(m[0]):]
|
|
|
|
m[2] = strings.TrimPrefix(m[2], "\"")
|
|
m[2] = strings.TrimSuffix(m[2], "\"")
|
|
ha.Values[m[1]] = m[2]
|
|
}
|
|
|
|
return ha, nil
|
|
}
|
|
|
|
// Write encodes an Authenticate or a WWW-Authenticate header.
|
|
func (ha *HeaderAuth) Write() HeaderValue {
|
|
ret := ha.Prefix + " "
|
|
|
|
// follow a specific order, otherwise some clients/servers do not work correctly
|
|
var sortedKeys []string
|
|
for key := range ha.Values {
|
|
sortedKeys = append(sortedKeys, key)
|
|
}
|
|
score := func(v string) int {
|
|
switch v {
|
|
case "username":
|
|
return 0
|
|
case "realm":
|
|
return 1
|
|
case "nonce":
|
|
return 2
|
|
case "uri":
|
|
return 3
|
|
case "response":
|
|
return 4
|
|
case "opaque":
|
|
return 5
|
|
case "stale":
|
|
return 6
|
|
case "algorithm":
|
|
return 7
|
|
}
|
|
return 8
|
|
}
|
|
sort.Slice(sortedKeys, func(a, b int) bool {
|
|
sa := score(sortedKeys[a])
|
|
sb := score(sortedKeys[b])
|
|
if sa != sb {
|
|
return sa < sb
|
|
}
|
|
return a < b
|
|
})
|
|
|
|
var tmp []string
|
|
for _, key := range sortedKeys {
|
|
tmp = append(tmp, key+"=\""+ha.Values[key]+"\"")
|
|
}
|
|
ret += strings.Join(tmp, ", ")
|
|
|
|
return HeaderValue{ret}
|
|
}
|