|
|
@@ -48,12 +48,12 @@ import (
|
|
|
func New(ctx context.Context) *grpc.Server {
|
|
|
s := grpc.NewServer(
|
|
|
grpc.ChainUnaryInterceptor(
|
|
|
- unaryMeta(ctx),
|
|
|
+ unaryServerInterceptor(ctx),
|
|
|
unary,
|
|
|
),
|
|
|
grpc.ChainStreamInterceptor(
|
|
|
grpc.StreamServerInterceptor(stream),
|
|
|
- grpc.StreamServerInterceptor(streamMeta(ctx)),
|
|
|
+ grpc.StreamServerInterceptor(streamServerInterceptor(ctx)),
|
|
|
),
|
|
|
)
|
|
|
hs := health.NewServer()
|
|
|
@@ -77,9 +77,11 @@ func stream(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo,
|
|
|
return grpc_prometheus.StreamServerInterceptor(srv, ss, info, handler)
|
|
|
}
|
|
|
|
|
|
-func unaryMeta(clictx context.Context) func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
|
|
+// unaryServerInterceptor configures the context and sends it to the next handler
|
|
|
+func unaryServerInterceptor(clictx context.Context) func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
|
|
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
|
|
- configuredCtx, err := configureContext(ctx, clictx)
|
|
|
+ currentContext := getContext(ctx)
|
|
|
+ configuredCtx, err := configureContext(clictx, currentContext)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
@@ -88,50 +90,66 @@ func unaryMeta(clictx context.Context) func(ctx context.Context, req interface{}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func streamMeta(clictx context.Context) func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
|
|
+// streamServerInterceptor configures the context and sends it to the next handler
|
|
|
+func streamServerInterceptor(clictx context.Context) func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
|
|
return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
|
|
- ctx, err := configureContext(ss.Context(), clictx)
|
|
|
+ currentContext := getContext(ss.Context())
|
|
|
+ ctx, err := configureContext(clictx, currentContext)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
- nss := newServerStream(ctx, ss)
|
|
|
-
|
|
|
- return handler(srv, nss)
|
|
|
+ return handler(srv, newServerStream(ctx, ss))
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// nolint: golint
|
|
|
-func configureContext(ctx context.Context, clictx context.Context) (context.Context, error) {
|
|
|
+// getContext returns the current context name sent in the request metadata, it
|
|
|
+// returns an empty string if there is no metadata
|
|
|
+// not present
|
|
|
+func getContext(ctx context.Context) string {
|
|
|
md, ok := metadata.FromIncomingContext(ctx)
|
|
|
if !ok {
|
|
|
- return ctx, nil
|
|
|
+ return ""
|
|
|
}
|
|
|
|
|
|
key, ok := md[apicontext.Key]
|
|
|
if !ok {
|
|
|
- return ctx, nil
|
|
|
+ return ""
|
|
|
}
|
|
|
|
|
|
if len(key) == 1 {
|
|
|
- s := store.ContextStore(clictx)
|
|
|
- ctx = store.WithContextStore(ctx, s)
|
|
|
- ctx = apicontext.WithCurrentContext(ctx, key[0])
|
|
|
+ return key[0]
|
|
|
+ }
|
|
|
|
|
|
- c, err := client.New(ctx)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
+ return ""
|
|
|
+}
|
|
|
|
|
|
- ctx, err = proxy.WithClient(ctx, c)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
+// configureContext populates the request context with objects the client
|
|
|
+// needs: the context store and the api client
|
|
|
+func configureContext(ctx context.Context, currentContext string) (context.Context, error) {
|
|
|
+ s := store.ContextStore(ctx)
|
|
|
+ ctx = store.WithContextStore(ctx, s)
|
|
|
+ if currentContext != "" {
|
|
|
+ ctx = apicontext.WithCurrentContext(ctx, currentContext)
|
|
|
+ }
|
|
|
+
|
|
|
+ c, err := client.New(ctx)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ ctx, err = proxy.WithClient(ctx, c)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
}
|
|
|
|
|
|
return ctx, nil
|
|
|
}
|
|
|
|
|
|
+// A gRPC server stream will only let you get its context but
|
|
|
+// there is no way to set a new (augmented context) to the next
|
|
|
+// handler (like we do for a unary request). We need to wrap the grpc.ServerSteam
|
|
|
+// to be able to set a new context that will be sent to the next stream interceptor.
|
|
|
type contextServerStream struct {
|
|
|
s grpc.ServerStream
|
|
|
ctx context.Context
|