1
18
19
20
21
22 package metadata
23
24 import (
25 "context"
26 "fmt"
27 "strings"
28
29 "google.golang.org/grpc/internal"
30 )
31
32 func init() {
33 internal.FromOutgoingContextRaw = fromOutgoingContextRaw
34 }
35
36
37
38
39 func DecodeKeyValue(k, v string) (string, string, error) {
40 return k, v, nil
41 }
42
43
44
45 type MD map[string][]string
46
47
48
49
50
51
52
53
54
55
56
57
58
59 func New(m map[string]string) MD {
60 md := make(MD, len(m))
61 for k, val := range m {
62 key := strings.ToLower(k)
63 md[key] = append(md[key], val)
64 }
65 return md
66 }
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 func Pairs(kv ...string) MD {
82 if len(kv)%2 == 1 {
83 panic(fmt.Sprintf("metadata: Pairs got the odd number of input pairs for metadata: %d", len(kv)))
84 }
85 md := make(MD, len(kv)/2)
86 for i := 0; i < len(kv); i += 2 {
87 key := strings.ToLower(kv[i])
88 md[key] = append(md[key], kv[i+1])
89 }
90 return md
91 }
92
93
94
95 func (md MD) String() string {
96 var sb strings.Builder
97 fmt.Fprintf(&sb, "MD{")
98 for k, v := range md {
99 if sb.Len() > 3 {
100 fmt.Fprintf(&sb, ", ")
101 }
102 fmt.Fprintf(&sb, "%s=[%s]", k, strings.Join(v, ", "))
103 }
104 fmt.Fprintf(&sb, "}")
105 return sb.String()
106 }
107
108
109 func (md MD) Len() int {
110 return len(md)
111 }
112
113
114 func (md MD) Copy() MD {
115 out := make(MD, len(md))
116 for k, v := range md {
117 out[k] = copyOf(v)
118 }
119 return out
120 }
121
122
123
124
125 func (md MD) Get(k string) []string {
126 k = strings.ToLower(k)
127 return md[k]
128 }
129
130
131
132
133 func (md MD) Set(k string, vals ...string) {
134 if len(vals) == 0 {
135 return
136 }
137 k = strings.ToLower(k)
138 md[k] = vals
139 }
140
141
142
143
144
145 func (md MD) Append(k string, vals ...string) {
146 if len(vals) == 0 {
147 return
148 }
149 k = strings.ToLower(k)
150 md[k] = append(md[k], vals...)
151 }
152
153
154
155 func (md MD) Delete(k string) {
156 k = strings.ToLower(k)
157 delete(md, k)
158 }
159
160
161
162
163
164 func Join(mds ...MD) MD {
165 out := MD{}
166 for _, md := range mds {
167 for k, v := range md {
168 out[k] = append(out[k], v...)
169 }
170 }
171 return out
172 }
173
174 type mdIncomingKey struct{}
175 type mdOutgoingKey struct{}
176
177
178
179 func NewIncomingContext(ctx context.Context, md MD) context.Context {
180 return context.WithValue(ctx, mdIncomingKey{}, md)
181 }
182
183
184
185
186
187 func NewOutgoingContext(ctx context.Context, md MD) context.Context {
188 return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md})
189 }
190
191
192
193
194 func AppendToOutgoingContext(ctx context.Context, kv ...string) context.Context {
195 if len(kv)%2 == 1 {
196 panic(fmt.Sprintf("metadata: AppendToOutgoingContext got an odd number of input pairs for metadata: %d", len(kv)))
197 }
198 md, _ := ctx.Value(mdOutgoingKey{}).(rawMD)
199 added := make([][]string, len(md.added)+1)
200 copy(added, md.added)
201 kvCopy := make([]string, 0, len(kv))
202 for i := 0; i < len(kv); i += 2 {
203 kvCopy = append(kvCopy, strings.ToLower(kv[i]), kv[i+1])
204 }
205 added[len(added)-1] = kvCopy
206 return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md.md, added: added})
207 }
208
209
210
211
212 func FromIncomingContext(ctx context.Context) (MD, bool) {
213 md, ok := ctx.Value(mdIncomingKey{}).(MD)
214 if !ok {
215 return nil, false
216 }
217 out := make(MD, len(md))
218 for k, v := range md {
219
220
221
222 key := strings.ToLower(k)
223 out[key] = copyOf(v)
224 }
225 return out, true
226 }
227
228
229
230
231
232
233
234
235
236 func ValueFromIncomingContext(ctx context.Context, key string) []string {
237 md, ok := ctx.Value(mdIncomingKey{}).(MD)
238 if !ok {
239 return nil
240 }
241
242 if v, ok := md[key]; ok {
243 return copyOf(v)
244 }
245 for k, v := range md {
246
247
248
249 if strings.EqualFold(k, key) {
250 return copyOf(v)
251 }
252 }
253 return nil
254 }
255
256 func copyOf(v []string) []string {
257 vals := make([]string, len(v))
258 copy(vals, v)
259 return vals
260 }
261
262
263
264
265
266
267
268 func fromOutgoingContextRaw(ctx context.Context) (MD, [][]string, bool) {
269 raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD)
270 if !ok {
271 return nil, nil, false
272 }
273
274 return raw.md, raw.added, true
275 }
276
277
278
279
280 func FromOutgoingContext(ctx context.Context) (MD, bool) {
281 raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD)
282 if !ok {
283 return nil, false
284 }
285
286 mdSize := len(raw.md)
287 for i := range raw.added {
288 mdSize += len(raw.added[i]) / 2
289 }
290
291 out := make(MD, mdSize)
292 for k, v := range raw.md {
293
294
295
296 key := strings.ToLower(k)
297 out[key] = copyOf(v)
298 }
299 for _, added := range raw.added {
300 if len(added)%2 == 1 {
301 panic(fmt.Sprintf("metadata: FromOutgoingContext got an odd number of input pairs for metadata: %d", len(added)))
302 }
303
304 for i := 0; i < len(added); i += 2 {
305 key := strings.ToLower(added[i])
306 out[key] = append(out[key], added[i+1])
307 }
308 }
309 return out, ok
310 }
311
312 type rawMD struct {
313 md MD
314 added [][]string
315 }
316
View as plain text