-
Notifications
You must be signed in to change notification settings - Fork 1
/
parser.go
79 lines (60 loc) · 1.57 KB
/
parser.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package nego
import (
"net/http"
"strconv"
"strings"
)
type accept map[string]float64
func (a accept) qvalue(offer string) (float64, bool) {
if qvalue, exists := a[offer]; exists {
return qvalue, exists
}
if !strings.Contains(offer, "/") {
qvalue, exists := a["*"]
return qvalue, exists
}
slashIndex := strings.Index(offer, "/")
if qvalue, exists := a[offer[:slashIndex]+"/*"]; exists {
return qvalue, exists
}
if qvalue, exists := a["*/*"]; exists {
return qvalue, exists
}
return 0.0, false
}
// parseAccept parses the values of a content negotiation header. The following request headers are sent
// by a user agent to engage in proactive negotiation: Accept, Accept-Charset, Accept-Encoding, Accept-Language.
func parseAccept(header http.Header, key string) (accept, bool) {
values, exists := header[key]
accepts := make(map[string]float64)
for _, value := range values {
if value == "" {
continue
}
for _, spec := range strings.Split(value, ",") {
name, qvalue := parseSpec(spec)
accepts[name] = qvalue
}
}
return accepts, exists
}
func parseSpec(spec string) (string, float64) {
qvalue := 1.0
sToken := strings.ReplaceAll(spec, " ", "")
parts := strings.Split(sToken, ";")
for _, param := range parts[1:] {
lowerParam := strings.ToLower(param)
qvalueStr := strings.TrimPrefix(lowerParam, "q=")
if qvalueStr != lowerParam {
qvalue = parseQuality(qvalueStr)
}
}
return parts[0], qvalue
}
func parseQuality(value string) float64 {
float, err := strconv.ParseFloat(value, 64)
if err != nil {
return -1
}
return float
}