diff --git a/metadata/context.go b/metadata/context.go deleted file mode 100644 index e05a37759..000000000 --- a/metadata/context.go +++ /dev/null @@ -1,46 +0,0 @@ -package metadata - -import ( - "context" - "fmt" -) - -type serverMetadataKey struct{} - -// NewServerContext creates a new context with client md attached. -func NewServerContext(ctx context.Context, md Metadata) context.Context { - return context.WithValue(ctx, serverMetadataKey{}, md) -} - -// FromServerContext returns the server metadata in ctx if it exists. -func FromServerContext(ctx context.Context) (Metadata, bool) { - md, ok := ctx.Value(serverMetadataKey{}).(Metadata) - return md, ok -} - -type clientMetadataKey struct{} - -// NewClientContext creates a new context with client md attached. -func NewClientContext(ctx context.Context, md Metadata) context.Context { - return context.WithValue(ctx, clientMetadataKey{}, md) -} - -// FromClientContext returns the client metadata in ctx if it exists. -func FromClientContext(ctx context.Context) (Metadata, bool) { - md, ok := ctx.Value(clientMetadataKey{}).(Metadata) - return md, ok -} - -// AppendToClientContext returns a new context with the provided kv merged -// with any existing metadata in the context. -func AppendToClientContext(ctx context.Context, kv ...string) context.Context { - if len(kv)%2 == 1 { - panic(fmt.Sprintf("metadata: AppendToOutgoingContext got an odd number of input pairs for metadata: %d", len(kv))) - } - md, _ := FromClientContext(ctx) - md = md.Clone() - for i := 0; i < len(kv); i += 2 { - md.Set(kv[i], kv[i+1]) - } - return NewClientContext(ctx, md) -} diff --git a/metadata/metadata.go b/metadata/metadata.go index 7cc225f24..21b7547db 100644 --- a/metadata/metadata.go +++ b/metadata/metadata.go @@ -1,6 +1,8 @@ package metadata import ( + "context" + "fmt" "strings" ) @@ -41,6 +43,16 @@ func (m Metadata) Set(key string, value string) { m[k] = value } +// Range iterate over element in metadata. +func (m Metadata) Range(f func(k, v string) bool) { + for k, v := range m { + ret := f(k, v) + if ret == false { + break + } + } +} + // Clone returns a deep copy of Metadata func (m Metadata) Clone() Metadata { md := Metadata{} @@ -49,3 +61,53 @@ func (m Metadata) Clone() Metadata { } return md } + +type serverMetadataKey struct{} + +// NewServerContext creates a new context with client md attached. +func NewServerContext(ctx context.Context, md Metadata) context.Context { + return context.WithValue(ctx, serverMetadataKey{}, md) +} + +// FromServerContext returns the server metadata in ctx if it exists. +func FromServerContext(ctx context.Context) (Metadata, bool) { + md, ok := ctx.Value(serverMetadataKey{}).(Metadata) + return md, ok +} + +type clientMetadataKey struct{} + +// NewClientContext creates a new context with client md attached. +func NewClientContext(ctx context.Context, md Metadata) context.Context { + return context.WithValue(ctx, clientMetadataKey{}, md) +} + +// FromClientContext returns the client metadata in ctx if it exists. +func FromClientContext(ctx context.Context) (Metadata, bool) { + md, ok := ctx.Value(clientMetadataKey{}).(Metadata) + return md, ok +} + +// AppendToClientContext returns a new context with the provided kv merged +// with any existing metadata in the context. +func AppendToClientContext(ctx context.Context, kv ...string) context.Context { + if len(kv)%2 == 1 { + panic(fmt.Sprintf("metadata: AppendToOutgoingContext got an odd number of input pairs for metadata: %d", len(kv))) + } + md, _ := FromClientContext(ctx) + md = md.Clone() + for i := 0; i < len(kv); i += 2 { + md.Set(kv[i], kv[i+1]) + } + return NewClientContext(ctx, md) +} + +// MergeToClientContext merge new metadata into ctx. +func MergeToClientContext(ctx context.Context, cmd Metadata) context.Context { + md, _ := FromClientContext(ctx) + md = md.Clone() + for k, v := range cmd { + md[k] = v + } + return NewClientContext(ctx, md) +} diff --git a/middleware/metadata/metadata.go b/middleware/metadata/metadata.go index ac1e76ed0..aaa566743 100644 --- a/middleware/metadata/metadata.go +++ b/middleware/metadata/metadata.go @@ -17,24 +17,24 @@ type options struct { md metadata.Metadata } -// WithConstants is option with constant metadata key value. +// WithConstants with constant metadata key value. func WithConstants(md metadata.Metadata) Option { return func(o *options) { o.md = md } } -// WithPropagatedPrefix is option with global propagated key prefix. +// WithPropagatedPrefix with propagated key prefix. func WithPropagatedPrefix(prefix ...string) Option { return func(o *options) { o.prefix = prefix } } -// Server is middleware client-side metadata. +// Server is middleware server-side metadata. func Server(opts ...Option) middleware.Middleware { options := options{ - prefix: []string{"x-md-global-", "x-md-local-"}, + prefix: []string{"x-md-"}, // x-md-global-, x-md-local } for _, o := range opts { o(&options) @@ -42,11 +42,10 @@ func Server(opts ...Option) middleware.Middleware { return func(handler middleware.Handler) middleware.Handler { return func(ctx context.Context, req interface{}) (reply interface{}, err error) { if tr, ok := transport.FromServerContext(ctx); ok { - md := metadata.Metadata{} + md := metadata.New() for _, k := range tr.Header().Keys() { - key := strings.ToLower(k) for _, prefix := range options.prefix { - if strings.HasPrefix(key, prefix) { + if strings.HasPrefix(strings.ToLower(k), prefix) { md.Set(k, tr.Header().Get(k)) break } @@ -70,6 +69,7 @@ func Client(opts ...Option) middleware.Middleware { return func(handler middleware.Handler) middleware.Handler { return func(ctx context.Context, req interface{}) (reply interface{}, err error) { if tr, ok := transport.FromClientContext(ctx); ok { + // x-md-local- for k, v := range options.md { tr.Header().Set(k, v) } @@ -78,6 +78,7 @@ func Client(opts ...Option) middleware.Middleware { tr.Header().Set(k, v) } } + // x-md-global- if md, ok := metadata.FromServerContext(ctx); ok { for k, v := range md { for _, prefix := range options.prefix {