|
|
|
package metadata
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"net/http"
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/go-kratos/kratos/v2/metadata"
|
|
|
|
"github.com/go-kratos/kratos/v2/transport"
|
|
|
|
)
|
|
|
|
|
|
|
|
type headerCarrier http.Header
|
|
|
|
|
|
|
|
func (hc headerCarrier) Get(key string) string { return http.Header(hc).Get(key) }
|
|
|
|
|
|
|
|
func (hc headerCarrier) Set(key string, value string) { http.Header(hc).Set(key, value) }
|
|
|
|
|
|
|
|
func (hc headerCarrier) Add(key string, value string) { http.Header(hc).Add(key, value) }
|
|
|
|
|
|
|
|
// Keys lists the keys stored in this carrier.
|
|
|
|
func (hc headerCarrier) Keys() []string {
|
|
|
|
keys := make([]string, 0, len(hc))
|
|
|
|
for k := range http.Header(hc) {
|
|
|
|
keys = append(keys, k)
|
|
|
|
}
|
|
|
|
return keys
|
|
|
|
}
|
|
|
|
|
|
|
|
// Values returns a slice value associated with the passed key.
|
|
|
|
func (hc headerCarrier) Values(key string) []string {
|
|
|
|
return http.Header(hc).Values(key)
|
|
|
|
}
|
|
|
|
|
|
|
|
type testTransport struct{ header headerCarrier }
|
|
|
|
|
|
|
|
func (tr *testTransport) Kind() transport.Kind { return transport.KindHTTP }
|
|
|
|
func (tr *testTransport) Endpoint() string { return "" }
|
|
|
|
func (tr *testTransport) Operation() string { return "" }
|
|
|
|
func (tr *testTransport) RequestHeader() transport.Header { return tr.header }
|
|
|
|
func (tr *testTransport) ReplyHeader() transport.Header { return tr.header }
|
|
|
|
|
|
|
|
var (
|
|
|
|
globalKey = "x-md-global-key"
|
|
|
|
globalValue = "global-value"
|
|
|
|
localKey = "x-md-local-key"
|
|
|
|
localValue = "local-value"
|
|
|
|
customKey = "x-md-local-custom"
|
|
|
|
customValue = "custom-value"
|
|
|
|
constKey = "x-md-local-const"
|
|
|
|
constValue = "x-md-local-const"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestSever(t *testing.T) {
|
|
|
|
hs := func(ctx context.Context, in interface{}) (interface{}, error) {
|
|
|
|
md, ok := metadata.FromServerContext(ctx)
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.New("no md")
|
|
|
|
}
|
|
|
|
if md.Get(constKey) != constValue {
|
|
|
|
return nil, errors.New("const not equal")
|
|
|
|
}
|
|
|
|
if md.Get(globalKey) != globalValue {
|
|
|
|
return nil, errors.New("global not equal")
|
|
|
|
}
|
|
|
|
if md.Get(localKey) != localValue {
|
|
|
|
return nil, errors.New("local not equal")
|
|
|
|
}
|
|
|
|
return in, nil
|
|
|
|
}
|
|
|
|
hc := headerCarrier{}
|
|
|
|
hc.Set(globalKey, globalValue)
|
|
|
|
hc.Set(localKey, localValue)
|
|
|
|
ctx := transport.NewServerContext(context.Background(), &testTransport{hc})
|
|
|
|
// const md
|
|
|
|
constMD := metadata.New()
|
|
|
|
constMD.Set(constKey, constValue)
|
|
|
|
reply, err := Server(WithConstants(constMD))(hs)(ctx, "foo")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if reply.(string) != "foo" {
|
|
|
|
t.Fatalf("want foo got %v", reply)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestClient(t *testing.T) {
|
|
|
|
hs := func(ctx context.Context, in interface{}) (interface{}, error) {
|
|
|
|
tr, ok := transport.FromClientContext(ctx)
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.New("no md")
|
|
|
|
}
|
|
|
|
if tr.RequestHeader().Get(constKey) != constValue {
|
|
|
|
return nil, errors.New("const not equal")
|
|
|
|
}
|
|
|
|
if tr.RequestHeader().Get(customKey) != customValue {
|
|
|
|
return nil, errors.New("custom not equal")
|
|
|
|
}
|
|
|
|
if tr.RequestHeader().Get(globalKey) != globalValue {
|
|
|
|
return nil, errors.New("global not equal")
|
|
|
|
}
|
|
|
|
if tr.RequestHeader().Get(localKey) != "" {
|
|
|
|
return nil, errors.New("local must empty")
|
|
|
|
}
|
|
|
|
return in, nil
|
|
|
|
}
|
|
|
|
// server md
|
|
|
|
serverMD := metadata.New()
|
|
|
|
serverMD.Set(globalKey, globalValue)
|
|
|
|
serverMD.Set(localKey, localValue)
|
|
|
|
ctx := metadata.NewServerContext(context.Background(), serverMD)
|
|
|
|
// client md
|
|
|
|
clientMD := metadata.New()
|
|
|
|
clientMD.Set(customKey, customValue)
|
|
|
|
ctx = metadata.NewClientContext(ctx, clientMD)
|
|
|
|
// transport carrier
|
|
|
|
ctx = transport.NewClientContext(ctx, &testTransport{headerCarrier{}})
|
|
|
|
// const md
|
|
|
|
constMD := metadata.New()
|
|
|
|
constMD.Set(constKey, constValue)
|
|
|
|
reply, err := Client(WithConstants(constMD))(hs)(ctx, "bar")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if reply.(string) != "bar" {
|
|
|
|
t.Fatalf("want foo got %v", reply)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWithConstants(t *testing.T) {
|
|
|
|
md := metadata.Metadata{
|
|
|
|
constKey: {constValue},
|
|
|
|
}
|
|
|
|
options := &options{
|
|
|
|
md: metadata.Metadata{
|
|
|
|
"override": {"override"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
WithConstants(md)(options)
|
|
|
|
if !reflect.DeepEqual(md, options.md) {
|
|
|
|
t.Errorf("want: %v, got: %v", md, options.md)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestOptions_WithPropagatedPrefix(t *testing.T) {
|
|
|
|
options := &options{
|
|
|
|
prefix: []string{"override"},
|
|
|
|
}
|
|
|
|
prefixes := []string{"something", "another"}
|
|
|
|
|
|
|
|
WithPropagatedPrefix(prefixes...)(options)
|
|
|
|
if !reflect.DeepEqual(prefixes, options.prefix) {
|
|
|
|
t.Error("The prefix must be overridden.")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestOptions_hasPrefix(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
options *options
|
|
|
|
key string
|
|
|
|
exists bool
|
|
|
|
}{
|
|
|
|
{"exists key upper", &options{prefix: []string{"prefix"}}, "PREFIX_true", true},
|
|
|
|
{"exists key lower", &options{prefix: []string{"prefix"}}, "prefix_true", true},
|
|
|
|
{"not exists key upper", &options{prefix: []string{"prefix"}}, "false_PREFIX", false},
|
|
|
|
{"not exists key lower", &options{prefix: []string{"prefix"}}, "false_prefix", false},
|
|
|
|
}
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
|
|
|
exists := test.options.hasPrefix(test.key)
|
|
|
|
if test.exists != exists {
|
|
|
|
t.Errorf("key: '%sr', not exists prefixs: %v", test.key, test.options.prefix)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|