-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathheader.go
89 lines (69 loc) · 1.59 KB
/
header.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
80
81
82
83
84
85
86
87
88
89
package servertiming
import (
"fmt"
"net/http"
"regexp"
"strings"
"sync"
"time"
"github.com/golang/gddo/httputil/header"
)
const HeaderKey = "Server-Timing"
type Header struct {
Metrics []*Metric
sync.Mutex
}
func ParseHeader(input string) (*Header, error) {
rawMetrics := header.ParseList(headerParams(input))
metrics := make([]*Metric, 0, len(rawMetrics))
for _, raw := range rawMetrics {
var m Metric
m.Name, m.Extra = header.ParseValueAndParams(headerParams(raw))
if v, ok := m.Extra[paramNameDesc]; ok {
m.Desc = v
delete(m.Extra, paramNameDesc)
}
if v, ok := m.Extra[paramNameDur]; ok {
m.Duration, _ = time.ParseDuration(v + "ms")
delete(m.Extra, paramNameDur)
}
metrics = append(metrics, &m)
}
return &Header{Metrics: metrics}, nil
}
func (h *Header) NewMetric(name string) *Metric {
return h.Add(&Metric{Name: name})
}
func (h *Header) Add(m *Metric) *Metric {
if h == nil {
return m
}
h.Lock()
defer h.Unlock()
h.Metrics = append(h.Metrics, m)
return m
}
func (h *Header) String() string {
parts := make([]string, 0, len(h.Metrics))
for _, m := range h.Metrics {
parts = append(parts, m.String())
}
return strings.Join(parts, ",")
}
const (
paramNameDesc = "desc"
paramNameDur = "dur"
)
func headerParams(s string) (http.Header, string) {
const key = "Key"
return http.Header(map[string][]string{
key: {s},
}), key
}
var reNumber = regexp.MustCompile(`^\d+\.?\d*$`)
func headerEncodeParam(key, value string) string {
if reNumber.MatchString(value) {
return fmt.Sprintf(`%s=%s`, key, value)
}
return fmt.Sprintf(`%s=%q`, key, value)
}