-
Notifications
You must be signed in to change notification settings - Fork 0
/
header.go
125 lines (112 loc) · 2.64 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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package hyper
import (
"context"
"fmt"
"net/http"
"strings"
"sync"
"github.com/infiniteloopcloud/log"
)
const HeaderPrefix = "Ctx_"
func FromHeader(ctx context.Context, header http.Header, contextKeys map[string]log.ContextField) context.Context {
for k, h := range header {
if strings.Contains(k, HeaderPrefix) {
if len(h) > 0 {
key := strings.ReplaceAll(k, HeaderPrefix, "")
if ctx.Value(key) == nil {
ctx = context.WithValue(ctx, contextKeys[key], h[0])
}
}
}
}
return ctx
}
func IntoHeader(ctx context.Context, header http.Header, contextKeys map[string]log.ContextField) http.Header {
h := copyHeader(header)
kv := GetValues(ctx, contextKeys)
for k := range kv {
if key, ok := k.(log.ContextField); ok {
h = ElementIntoHeader(ctx, h, key)
}
}
return h
}
func ElementIntoHeader(ctx context.Context, header http.Header, key log.ContextField) http.Header {
h := copyHeader(header)
v := ctx.Value(key)
if value, ok := v.(fmt.Stringer); ok {
h.Add(HeaderPrefix+string(key), value.String())
} else if value, ok := v.(string); ok {
h.Add(HeaderPrefix+string(key), value)
}
return h
}
func copyHeader(m http.Header) http.Header {
cp := make(map[string][]string)
for k := range m {
var s = make([]string, len(m[k]))
copy(s, m[k])
cp[k] = s
}
return cp
}
var castMutex = &sync.Mutex{}
func GetValues(ctx context.Context, contextKeys map[string]log.ContextField) map[interface{}]interface{} {
castMutex.Lock()
defer castMutex.Unlock()
m := make(map[interface{}]interface{})
for _, field := range contextKeys {
m[field] = ctx.Value(field)
}
// Temporary solution
// getValuesRecursive(ctx, m)
return m
}
// type iface struct {
// itab, data unsafe.Pointer
// }
//
// type valueCtx struct {
// context.Context
// key, val interface{}
// }
//
// func getValuesRecursive(ctx context.Context, m map[interface{}]interface{}) {
// if ctx == nil {
// return
// }
// rv := reflect.ValueOf(ctx)
// if rv.IsNil() || rv.IsZero() {
// return
// }
// ictxPtr := (*iface)(unsafe.Pointer(&ctx))
// if ictxPtr == nil {
// return
// }
// ictx := *ictxPtr
//
// rvUintptr := reflect.ValueOf(ictx.data)
// if rvUintptr.IsNil() {
// return
// }
//
// valCtx := (*valueCtx)(ictx.data)
// if valCtx != nil {
// copyValCtx := *valCtx
// if copyValCtx.key != nil && copyValCtx.val != nil {
// if copyValCtx.Context == nil {
// return
// }
// m[copyValCtx.key] = copyValCtx.val
// }
//
// if copyValCtx.Context == nil {
// return
// }
// rvValCtxContext := reflect.ValueOf(copyValCtx.Context)
// if rvValCtxContext.IsNil() || rvValCtxContext.IsZero() {
// return
// }
// getValuesRecursive(copyValCtx.Context, m)
// }
// }