| 
						
						
						
						 |  | @@ -1,7 +1,7 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | //go:build exclude |  |  |  | //go:build exclude | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | // TODO need compare with micro metadata |  |  |  | // Package metadata TODO need compare with micro metadata | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | package metadata |  |  |  | package metadata // import "google.golang.org/grpc/metadata" | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | import ( |  |  |  | import ( | 
			
		
	
		
		
			
				
					
					|  |  |  | 	"context" |  |  |  | 	"context" | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -9,16 +9,11 @@ import ( | 
			
		
	
		
		
			
				
					
					|  |  |  | 	"strings" |  |  |  | 	"strings" | 
			
		
	
		
		
			
				
					
					|  |  |  | ) |  |  |  | ) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | // DecodeKeyValue returns k, v, nil. |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | // |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | // Deprecated: use k and v directly instead. |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | func DecodeKeyValue(k, v string) (string, string, error) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return k, v, nil |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | // MD is a mapping from metadata keys to values. Users should use the following |  |  |  | // MD is a mapping from metadata keys to values. Users should use the following | 
			
		
	
		
		
			
				
					
					|  |  |  | // two convenience functions New and Pairs to generate MD. |  |  |  | // two convenience functions New and Pairs to generate MD. | 
			
		
	
		
		
			
				
					
					|  |  |  | type MD map[string]string |  |  |  | type MD map[string][]string | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | type Metadata map[string]string | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | // New creates an MD from a given key-value map. |  |  |  | // New creates an MD from a given key-value map. | 
			
		
	
		
		
			
				
					
					|  |  |  | // |  |  |  | // | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -36,7 +31,7 @@ func New(m map[string]string) MD { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	md := make(MD, len(m)) |  |  |  | 	md := make(MD, len(m)) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	for k, val := range m { |  |  |  | 	for k, val := range m { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		key := strings.ToLower(k) |  |  |  | 		key := strings.ToLower(k) | 
			
		
	
		
		
			
				
					
					|  |  |  | 		md[key] = val |  |  |  | 		md[key] = append(md[key], val) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return md |  |  |  | 	return md | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -61,7 +56,7 @@ func Pairs(kv ...string) MD { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	md := make(MD, len(kv)/2) |  |  |  | 	md := make(MD, len(kv)/2) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	for i := 0; i < len(kv); i += 2 { |  |  |  | 	for i := 0; i < len(kv); i += 2 { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		key := strings.ToLower(kv[i]) |  |  |  | 		key := strings.ToLower(kv[i]) | 
			
		
	
		
		
			
				
					
					|  |  |  | 		md[key] = kv[i+1] |  |  |  | 		md[key] = append(md[key], kv[i+1]) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return md |  |  |  | 	return md | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -75,7 +70,7 @@ func (md MD) Len() int { | 
			
		
	
		
		
			
				
					
					|  |  |  | func (md MD) Copy() MD { |  |  |  | func (md MD) Copy() MD { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	out := make(MD, len(md)) |  |  |  | 	out := make(MD, len(md)) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	for k, v := range md { |  |  |  | 	for k, v := range md { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		out[k] = v |  |  |  | 		out[k] = copyOf(v) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return out |  |  |  | 	return out | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -83,7 +78,7 @@ func (md MD) Copy() MD { | 
			
		
	
		
		
			
				
					
					|  |  |  | // Get obtains the values for a given key. |  |  |  | // Get obtains the values for a given key. | 
			
		
	
		
		
			
				
					
					|  |  |  | // |  |  |  | // | 
			
		
	
		
		
			
				
					
					|  |  |  | // k is converted to lowercase before searching in md. |  |  |  | // k is converted to lowercase before searching in md. | 
			
		
	
		
		
			
				
					
					|  |  |  | func (md MD) Get(k string) string { |  |  |  | func (md MD) Get(k string) []string { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	k = strings.ToLower(k) |  |  |  | 	k = strings.ToLower(k) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return md[k] |  |  |  | 	return md[k] | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -91,7 +86,7 @@ func (md MD) Get(k string) string { | 
			
		
	
		
		
			
				
					
					|  |  |  | // Set sets the value of a given key with a slice of values. |  |  |  | // Set sets the value of a given key with a slice of values. | 
			
		
	
		
		
			
				
					
					|  |  |  | // |  |  |  | // | 
			
		
	
		
		
			
				
					
					|  |  |  | // k is converted to lowercase before storing in md. |  |  |  | // k is converted to lowercase before storing in md. | 
			
		
	
		
		
			
				
					
					|  |  |  | func (md MD) Set(k string, vals string) { |  |  |  | func (md MD) Set(k string, vals ...string) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	if len(vals) == 0 { |  |  |  | 	if len(vals) == 0 { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return |  |  |  | 		return | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -103,12 +98,12 @@ func (md MD) Set(k string, vals string) { | 
			
		
	
		
		
			
				
					
					|  |  |  | // that key. |  |  |  | // that key. | 
			
		
	
		
		
			
				
					
					|  |  |  | // |  |  |  | // | 
			
		
	
		
		
			
				
					
					|  |  |  | // k is converted to lowercase before storing in md. |  |  |  | // k is converted to lowercase before storing in md. | 
			
		
	
		
		
			
				
					
					|  |  |  | func (md MD) Append(k string, vals string) { |  |  |  | func (md MD) Append(k string, vals ...string) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	if len(vals) == 0 { |  |  |  | 	if len(vals) == 0 { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return |  |  |  | 		return | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	k = strings.ToLower(k) |  |  |  | 	k = strings.ToLower(k) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	md[k] = vals |  |  |  | 	md[k] = append(md[k], vals...) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | // Delete removes the values for a given key k which is converted to lowercase |  |  |  | // Delete removes the values for a given key k which is converted to lowercase | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -126,7 +121,7 @@ func Join(mds ...MD) MD { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	out := MD{} |  |  |  | 	out := MD{} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	for _, md := range mds { |  |  |  | 	for _, md := range mds { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		for k, v := range md { |  |  |  | 		for k, v := range md { | 
			
		
	
		
		
			
				
					
					|  |  |  | 			out[k] = v |  |  |  | 			out[k] = append(out[k], v...) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return out |  |  |  | 	return out | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -137,16 +132,26 @@ type mdOutgoingKey struct{} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | // NewIncomingContext creates a new context with incoming md attached. md must |  |  |  | // NewIncomingContext creates a new context with incoming md attached. md must | 
			
		
	
		
		
			
				
					
					|  |  |  | // not be modified after calling this function. |  |  |  | // not be modified after calling this function. | 
			
		
	
		
		
			
				
					
					|  |  |  | func NewIncomingContext(ctx context.Context, md MD) context.Context { |  |  |  | func NewIncomingContext(ctx context.Context, md Metadata) context.Context { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	return context.WithValue(ctx, mdIncomingKey{}, md) |  |  |  | 	in := make(MD, len(md)) | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	for k, v := range md { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		in[k] = []string{v} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	return context.WithValue(ctx, mdIncomingKey{}, in) | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | // NewOutgoingContext creates a new context with outgoing md attached. If used |  |  |  | // NewOutgoingContext creates a new context with outgoing md attached. If used | 
			
		
	
		
		
			
				
					
					|  |  |  | // in conjunction with AppendToOutgoingContext, NewOutgoingContext will |  |  |  | // in conjunction with AppendToOutgoingContext, NewOutgoingContext will | 
			
		
	
		
		
			
				
					
					|  |  |  | // overwrite any previously-appended metadata. md must not be modified after |  |  |  | // overwrite any previously-appended metadata. md must not be modified after | 
			
		
	
		
		
			
				
					
					|  |  |  | // calling this function. |  |  |  | // calling this function. | 
			
		
	
		
		
			
				
					
					|  |  |  | func NewOutgoingContext(ctx context.Context, md MD) context.Context { |  |  |  | func NewOutgoingContext(ctx context.Context, md Metadata) context.Context { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md}) |  |  |  | 	out := make(MD, len(md)) | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	for k, v := range md { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		out[k] = []string{v} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: out}) | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | // AppendToOutgoingContext returns a new context with the provided kv merged |  |  |  | // AppendToOutgoingContext returns a new context with the provided kv merged | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -157,70 +162,121 @@ func AppendToOutgoingContext(ctx context.Context, kv ...string) context.Context | 
			
		
	
		
		
			
				
					
					|  |  |  | 		panic(fmt.Sprintf("metadata: AppendToOutgoingContext got an odd number of input pairs for metadata: %d", len(kv))) |  |  |  | 		panic(fmt.Sprintf("metadata: AppendToOutgoingContext got an odd number of input pairs for metadata: %d", len(kv))) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	md, _ := ctx.Value(mdOutgoingKey{}).(rawMD) |  |  |  | 	md, _ := ctx.Value(mdOutgoingKey{}).(rawMD) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	added := make([][]string, len(md.added)+1) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	copy(added, md.added) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	kvCopy := make([]string, 0, len(kv)) |  |  |  | 	kvCopy := make([]string, 0, len(kv)) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	for i := 0; i < len(kv); i += 2 { |  |  |  | 	for i := 0; i < len(kv); i += 2 { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		kvCopy = append(kvCopy, strings.ToLower(kv[i]), kv[i+1]) |  |  |  | 		kvCopy = append(kvCopy, strings.ToLower(kv[i]), kv[i+1]) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	added[len(added)-1] = kvCopy | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md.md}) |  |  |  | 	return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md.md, added: added}) | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | // FromIncomingContext returns the incoming metadata in ctx if it exists. |  |  |  | // FromIncomingContext returns the incoming metadata in ctx if it exists. | 
			
		
	
		
		
			
				
					
					|  |  |  | // |  |  |  | // | 
			
		
	
		
		
			
				
					
					|  |  |  | // All keys in the returned MD are lowercase. |  |  |  | // All keys in the returned MD are lowercase. | 
			
		
	
		
		
			
				
					
					|  |  |  | func FromIncomingContext(ctx context.Context) (MD, bool) { |  |  |  | func FromIncomingContext(ctx context.Context) (Metadata, bool) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	md, ok := ctx.Value(mdIncomingKey{}).(MD) |  |  |  | 	md, ok := ctx.Value(mdIncomingKey{}).(MD) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if !ok { |  |  |  | 	if !ok { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return nil, false |  |  |  | 		return nil, false | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	out := make(MD, len(md)) |  |  |  | 	out := make(Metadata, len(md)) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	for k, v := range md { |  |  |  | 	for k, v := range md { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		// We need to manually convert all keys to lower case, because MD is a |  |  |  | 		// We need to manually convert all keys to lower case, because MD is a | 
			
		
	
		
		
			
				
					
					|  |  |  | 		// map, and there's no guarantee that the MD attached to the context is |  |  |  | 		// map, and there's no guarantee that the MD attached to the context is | 
			
		
	
		
		
			
				
					
					|  |  |  | 		// created using our helper functions. |  |  |  | 		// created using our helper functions. | 
			
		
	
		
		
			
				
					
					|  |  |  | 		key := strings.ToLower(k) |  |  |  |  | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		out[key] = v |  |  |  | 		if len(v) > 0 { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			key := strings.ToLower(k) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			out[key] = v[0] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return out, true |  |  |  | 	return out, true | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | // ValueFromIncomingContext returns the metadata value corresponding to the metadata | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | // key from the incoming metadata if it exists. Keys are matched in a case insensitive | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | // manner. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | func ValueFromIncomingContext(ctx context.Context, key string) []string { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	md, ok := ctx.Value(mdIncomingKey{}).(MD) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if !ok { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		return nil | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if v, ok := md[key]; ok { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		return copyOf(v) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	for k, v := range md { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		// Case insensitive comparison: MD is a map, and there's no guarantee | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		// that the MD attached to the context is created using our helper | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		// functions. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if strings.EqualFold(k, key) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			return copyOf(v) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	return nil | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | func copyOf(v []string) []string { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	vals := make([]string, len(v)) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	copy(vals, v) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	return vals | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | // fromOutgoingContextRaw returns the un-merged, intermediary contents of rawMD. |  |  |  | // fromOutgoingContextRaw returns the un-merged, intermediary contents of rawMD. | 
			
		
	
		
		
			
				
					
					|  |  |  | // |  |  |  | // | 
			
		
	
		
		
			
				
					
					|  |  |  | // Remember to perform strings.ToLower on the keys, for both the returned MD (MD |  |  |  | // Remember to perform strings.ToLower on the keys, for both the returned MD (MD | 
			
		
	
		
		
			
				
					
					|  |  |  | // is a map, there's no guarantee it's created using our helper functions) and |  |  |  | // is a map, there's no guarantee it's created using our helper functions) and | 
			
		
	
		
		
			
				
					
					|  |  |  | // the extra kv pairs (AppendToOutgoingContext doesn't turn them into |  |  |  | // the extra kv pairs (AppendToOutgoingContext doesn't turn them into | 
			
		
	
		
		
			
				
					
					|  |  |  | // lowercase). |  |  |  | // lowercase). | 
			
		
	
		
		
			
				
					
					|  |  |  | func fromOutgoingContextRaw(ctx context.Context) (MD, bool) { |  |  |  | func fromOutgoingContextRaw(ctx context.Context) (MD, [][]string, bool) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD) |  |  |  | 	raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if !ok { |  |  |  | 	if !ok { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return nil, false |  |  |  | 		return nil, nil, false | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return raw.md, true |  |  |  | 	return raw.md, raw.added, true | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | // FromOutgoingContext returns the outgoing metadata in ctx if it exists. |  |  |  | // FromOutgoingContext returns the outgoing metadata in ctx if it exists. | 
			
		
	
		
		
			
				
					
					|  |  |  | // |  |  |  | // | 
			
		
	
		
		
			
				
					
					|  |  |  | // All keys in the returned MD are lowercase. |  |  |  | // All keys in the returned MD are lowercase. | 
			
		
	
		
		
			
				
					
					|  |  |  | func FromOutgoingContext(ctx context.Context) (MD, bool) { |  |  |  | func FromOutgoingContext(ctx context.Context) (Metadata, bool) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD) |  |  |  | 	raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if !ok { |  |  |  | 	if !ok { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return nil, false |  |  |  | 		return nil, false | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	out := make(MD, len(raw.md)) |  |  |  | 	mdSize := len(raw.md) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	for i := range raw.added { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		mdSize += len(raw.added[i]) / 2 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	out := make(Metadata, mdSize) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	for k, v := range raw.md { |  |  |  | 	for k, v := range raw.md { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		// We need to manually convert all keys to lower case, because MD is a |  |  |  | 		// We need to manually convert all keys to lower case, because MD is a | 
			
		
	
		
		
			
				
					
					|  |  |  | 		// map, and there's no guarantee that the MD attached to the context is |  |  |  | 		// map, and there's no guarantee that the MD attached to the context is | 
			
		
	
		
		
			
				
					
					|  |  |  | 		// created using our helper functions. |  |  |  | 		// created using our helper functions. | 
			
		
	
		
		
			
				
					
					|  |  |  | 		key := strings.ToLower(k) |  |  |  | 		if len(v) > 0 { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		out[key] = v |  |  |  | 			key := strings.ToLower(k) | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			out[key] = v[0] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	for _, added := range raw.added { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if len(added)%2 == 1 { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			panic(fmt.Sprintf("metadata: FromOutgoingContext got an odd number of input pairs for metadata: %d", len(added))) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		for i := 0; i < len(added); i += 2 { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			key := strings.ToLower(added[i]) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			out[key] = added[i+1] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return out, ok |  |  |  | 	return out, ok | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | type rawMD struct { |  |  |  | type rawMD struct { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	md MD |  |  |  | 	md    MD | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	added [][]string | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					
					| 
						
						
						
						 |  |   |