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.
kratos/middleware/metadata/metadata.go

101 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()
for _, k := range tr.Header().Keys() {
if options.hasPrefix(k) {
md.Set(k, tr.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 {
// x-md-local-
for k, v := range options.md {
tr.Header().Set(k, v)
}
if md, ok := metadata.FromClientContext(ctx); ok {
for k, v := range md {
tr.Header().Set(k, v)
}
}
// x-md-global-
if md, ok := metadata.FromServerContext(ctx); ok {
for k, v := range md {
if options.hasPrefix(k) {
tr.Header().Set(k, v)
}
}
}
}
return handler(ctx, req)
}
}
}