You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
102 lines
2.3 KiB
102 lines
2.3 KiB
package metadata |
|
|
|
import ( |
|
"context" |
|
"strings" |
|
|
|
"github.com/go-kratos/kratos/v2/metadata" |
|
"github.com/go-kratos/kratos/v2/middleware" |
|
"github.com/go-kratos/kratos/v2/transport" |
|
) |
|
|
|
// Option is metadata option. |
|
type Option func(*options) |
|
|
|
type options struct { |
|
prefix []string |
|
md metadata.Metadata |
|
} |
|
|
|
func (o *options) hasPrefix(key string) bool { |
|
k := strings.ToLower(key) |
|
for _, prefix := range o.prefix { |
|
if strings.HasPrefix(k, prefix) { |
|
return true |
|
} |
|
} |
|
return false |
|
} |
|
|
|
// WithConstants with constant metadata key value. |
|
func WithConstants(md metadata.Metadata) Option { |
|
return func(o *options) { |
|
o.md = md |
|
} |
|
} |
|
|
|
// WithPropagatedPrefix with propagated key prefix. |
|
func WithPropagatedPrefix(prefix ...string) Option { |
|
return func(o *options) { |
|
o.prefix = prefix |
|
} |
|
} |
|
|
|
// Server is middleware server-side metadata. |
|
func Server(opts ...Option) middleware.Middleware { |
|
options := &options{ |
|
prefix: []string{"x-md-"}, // x-md-global-, x-md-local |
|
} |
|
for _, o := range opts { |
|
o(options) |
|
} |
|
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 := options.md.Clone() |
|
header := tr.RequestHeader() |
|
for _, k := range header.Keys() { |
|
if options.hasPrefix(k) { |
|
md.Set(k, header.Get(k)) |
|
} |
|
} |
|
ctx = metadata.NewServerContext(ctx, md) |
|
} |
|
return handler(ctx, req) |
|
} |
|
} |
|
} |
|
|
|
// Client is middleware client-side metadata. |
|
func Client(opts ...Option) middleware.Middleware { |
|
options := &options{ |
|
prefix: []string{"x-md-global-"}, |
|
} |
|
for _, o := range opts { |
|
o(options) |
|
} |
|
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 { |
|
header := tr.RequestHeader() |
|
// x-md-local- |
|
for k, v := range options.md { |
|
header.Set(k, v) |
|
} |
|
if md, ok := metadata.FromClientContext(ctx); ok { |
|
for k, v := range md { |
|
header.Set(k, v) |
|
} |
|
} |
|
// x-md-global- |
|
if md, ok := metadata.FromServerContext(ctx); ok { |
|
for k, v := range md { |
|
if options.hasPrefix(k) { |
|
header.Set(k, v) |
|
} |
|
} |
|
} |
|
} |
|
return handler(ctx, req) |
|
} |
|
} |
|
}
|
|
|