gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/grpc/metadata/metadata.go (about) 1 /* 2 * 3 * Copyright 2014 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 // Package metadata define the structure of the metadata supported by gRPC library. 20 // Please refer to https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md 21 // for more information about custom-metadata. 22 package metadata // import "gitee.com/ks-custle/core-gm/grpc/metadata" 23 24 import ( 25 "context" 26 "fmt" 27 "strings" 28 ) 29 30 // DecodeKeyValue returns k, v, nil. 31 // 32 // Deprecated: use k and v directly instead. 33 func DecodeKeyValue(k, v string) (string, string, error) { 34 return k, v, nil 35 } 36 37 // MD is a mapping from metadata keys to values. Users should use the following 38 // two convenience functions New and Pairs to generate MD. 39 type MD map[string][]string 40 41 // New creates an MD from a given key-value map. 42 // 43 // Only the following ASCII characters are allowed in keys: 44 // - digits: 0-9 45 // - uppercase letters: A-Z (normalized to lower) 46 // - lowercase letters: a-z 47 // - special characters: -_. 48 // 49 // Uppercase letters are automatically converted to lowercase. 50 // 51 // Keys beginning with "grpc-" are reserved for grpc-internal use only and may 52 // result in errors if set in metadata. 53 func New(m map[string]string) MD { 54 md := MD{} 55 for k, val := range m { 56 key := strings.ToLower(k) 57 md[key] = append(md[key], val) 58 } 59 return md 60 } 61 62 // Pairs returns an MD formed by the mapping of key, value ... 63 // Pairs panics if len(kv) is odd. 64 // 65 // Only the following ASCII characters are allowed in keys: 66 // - digits: 0-9 67 // - uppercase letters: A-Z (normalized to lower) 68 // - lowercase letters: a-z 69 // - special characters: -_. 70 // 71 // Uppercase letters are automatically converted to lowercase. 72 // 73 // Keys beginning with "grpc-" are reserved for grpc-internal use only and may 74 // result in errors if set in metadata. 75 func Pairs(kv ...string) MD { 76 if len(kv)%2 == 1 { 77 panic(fmt.Sprintf("metadata: Pairs got the odd number of input pairs for metadata: %d", len(kv))) 78 } 79 md := MD{} 80 for i := 0; i < len(kv); i += 2 { 81 key := strings.ToLower(kv[i]) 82 md[key] = append(md[key], kv[i+1]) 83 } 84 return md 85 } 86 87 // Len returns the number of items in md. 88 func (md MD) Len() int { 89 return len(md) 90 } 91 92 // Copy returns a copy of md. 93 func (md MD) Copy() MD { 94 return Join(md) 95 } 96 97 // Get obtains the values for a given key. 98 // 99 // k is converted to lowercase before searching in md. 100 func (md MD) Get(k string) []string { 101 k = strings.ToLower(k) 102 return md[k] 103 } 104 105 // Set sets the value of a given key with a slice of values. 106 // 107 // k is converted to lowercase before storing in md. 108 func (md MD) Set(k string, vals ...string) { 109 if len(vals) == 0 { 110 return 111 } 112 k = strings.ToLower(k) 113 md[k] = vals 114 } 115 116 // Append adds the values to key k, not overwriting what was already stored at 117 // that key. 118 // 119 // k is converted to lowercase before storing in md. 120 func (md MD) Append(k string, vals ...string) { 121 if len(vals) == 0 { 122 return 123 } 124 k = strings.ToLower(k) 125 md[k] = append(md[k], vals...) 126 } 127 128 // Delete removes the values for a given key k which is converted to lowercase 129 // before removing it from md. 130 func (md MD) Delete(k string) { 131 k = strings.ToLower(k) 132 delete(md, k) 133 } 134 135 // Join joins any number of mds into a single MD. 136 // 137 // The order of values for each key is determined by the order in which the mds 138 // containing those values are presented to Join. 139 func Join(mds ...MD) MD { 140 out := MD{} 141 for _, md := range mds { 142 for k, v := range md { 143 out[k] = append(out[k], v...) 144 } 145 } 146 return out 147 } 148 149 type mdIncomingKey struct{} 150 type mdOutgoingKey struct{} 151 152 // NewIncomingContext creates a new context with incoming md attached. 153 func NewIncomingContext(ctx context.Context, md MD) context.Context { 154 return context.WithValue(ctx, mdIncomingKey{}, md) 155 } 156 157 // NewOutgoingContext creates a new context with outgoing md attached. If used 158 // in conjunction with AppendToOutgoingContext, NewOutgoingContext will 159 // overwrite any previously-appended metadata. 160 func NewOutgoingContext(ctx context.Context, md MD) context.Context { 161 return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md}) 162 } 163 164 // AppendToOutgoingContext returns a new context with the provided kv merged 165 // with any existing metadata in the context. Please refer to the documentation 166 // of Pairs for a description of kv. 167 func AppendToOutgoingContext(ctx context.Context, kv ...string) context.Context { 168 if len(kv)%2 == 1 { 169 panic(fmt.Sprintf("metadata: AppendToOutgoingContext got an odd number of input pairs for metadata: %d", len(kv))) 170 } 171 md, _ := ctx.Value(mdOutgoingKey{}).(rawMD) 172 added := make([][]string, len(md.added)+1) 173 copy(added, md.added) 174 added[len(added)-1] = make([]string, len(kv)) 175 copy(added[len(added)-1], kv) 176 return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md.md, added: added}) 177 } 178 179 // FromIncomingContext returns the incoming metadata in ctx if it exists. 180 // 181 // All keys in the returned MD are lowercase. 182 func FromIncomingContext(ctx context.Context) (MD, bool) { 183 md, ok := ctx.Value(mdIncomingKey{}).(MD) 184 if !ok { 185 return nil, false 186 } 187 out := MD{} 188 for k, v := range md { 189 // We need to manually convert all keys to lower case, because MD is a 190 // map, and there's no guarantee that the MD attached to the context is 191 // created using our helper functions. 192 key := strings.ToLower(k) 193 out[key] = v 194 } 195 return out, true 196 } 197 198 // FromOutgoingContextRaw returns the un-merged, intermediary contents of rawMD. 199 // 200 // Remember to perform strings.ToLower on the keys, for both the returned MD (MD 201 // is a map, there's no guarantee it's created using our helper functions) and 202 // the extra kv pairs (AppendToOutgoingContext doesn't turn them into 203 // lowercase). 204 // 205 // This is intended for gRPC-internal use ONLY. Users should use 206 // FromOutgoingContext instead. 207 func FromOutgoingContextRaw(ctx context.Context) (MD, [][]string, bool) { 208 raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD) 209 if !ok { 210 return nil, nil, false 211 } 212 213 return raw.md, raw.added, true 214 } 215 216 // FromOutgoingContext returns the outgoing metadata in ctx if it exists. 217 // 218 // All keys in the returned MD are lowercase. 219 func FromOutgoingContext(ctx context.Context) (MD, bool) { 220 raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD) 221 if !ok { 222 return nil, false 223 } 224 225 out := MD{} 226 for k, v := range raw.md { 227 // We need to manually convert all keys to lower case, because MD is a 228 // map, and there's no guarantee that the MD attached to the context is 229 // created using our helper functions. 230 key := strings.ToLower(k) 231 out[key] = v 232 } 233 for _, added := range raw.added { 234 if len(added)%2 == 1 { 235 panic(fmt.Sprintf("metadata: FromOutgoingContext got an odd number of input pairs for metadata: %d", len(added))) 236 } 237 238 for i := 0; i < len(added); i += 2 { 239 key := strings.ToLower(added[i]) 240 out[key] = append(out[key], added[i+1]) 241 } 242 } 243 return out, ok 244 } 245 246 type rawMD struct { 247 md MD 248 added [][]string 249 }