forked from thecodeteam/libstorage
-
Notifications
You must be signed in to change notification settings - Fork 0
/
handlers_instanceid.go
89 lines (76 loc) · 2.45 KB
/
handlers_instanceid.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 handlers
import (
"net/http"
"strings"
"github.com/codedellemc/libstorage/api/context"
"github.com/codedellemc/libstorage/api/types"
)
// instanceIDHandler is a global HTTP filter for grokking the InstanceIDs
// from the headers
type instanceIDHandler struct {
handler types.APIFunc
s2d map[string]string
}
// NewInstanceIDHandler returns a new global HTTP filter for grokking the
// InstanceIDs from the headers
func NewInstanceIDHandler(svcs <-chan types.StorageService) types.Middleware {
iidh := &instanceIDHandler{
s2d: map[string]string{},
}
for s := range svcs {
iidh.s2d[strings.ToLower(s.Name())] = strings.ToLower(s.Driver().Name())
}
return iidh
}
func (h *instanceIDHandler) Name() string {
return "instanceIDs-handler"
}
func (h *instanceIDHandler) Handler(m types.APIFunc) types.APIFunc {
return (&instanceIDHandler{m, h.s2d}).Handle
}
// Handle is the type's Handler function.
func (h *instanceIDHandler) Handle(
ctx types.Context,
w http.ResponseWriter,
req *http.Request,
store types.Store) error {
headers := req.Header[types.InstanceIDHeader]
ctx.WithField(types.InstanceIDHeader, headers).Debug("http header")
// this function has been updated to account for
// https://github.com/codedellemc/libstorage/pull/420 and
// https://github.com/codedellemc/rexray/issues/685.
//
// this handler now inspects each instance ID header and stores the
// unmarshaled object in one of two maps -- a map keyed by the
// service name and a map keyed by the driver name. the service
// name-keyed map is only used if the instance ID has a service
// name present.
//
// after the two maps are populated, all of the server's configured
// services are iterated. first we check the service name-keyed map
// for a service's instance ID, and only then if not present we
// check the driver name-keyed map for the service's instance ID.
valMap := types.InstanceIDMap{}
d2i := map[string]*types.InstanceID{}
s2i := map[string]*types.InstanceID{}
for _, h := range headers {
val := &types.InstanceID{}
if err := val.UnmarshalText([]byte(h)); err != nil {
return err
}
if len(val.Service) > 0 {
s2i[strings.ToLower(val.Service)] = val
} else {
d2i[strings.ToLower(val.Driver)] = val
}
}
for s, d := range h.s2d {
if iid, ok := s2i[s]; ok {
valMap[s] = iid
} else if iid, ok := d2i[d]; ok {
valMap[s] = iid
}
}
ctx = ctx.WithValue(context.AllInstanceIDsKey, valMap)
return h.handler(ctx, w, req, store)
}