diff --git a/grpc/client.go b/grpc/client.go index 210c835d1..43824b3f1 100644 --- a/grpc/client.go +++ b/grpc/client.go @@ -10,6 +10,7 @@ import ( "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/metadata" + "github.com/pace/bricks/http/middleware" "github.com/pace/bricks/http/security" "github.com/pace/bricks/locale" "github.com/pace/bricks/maintenance/log" @@ -72,14 +73,19 @@ func dialCtx(ctx context.Context, addr string) (*grpc.ClientConn, error) { func prepareClientContext(ctx context.Context) context.Context { if loc, ok := locale.FromCtx(ctx); ok { - ctx = metadata.AppendToOutgoingContext(ctx, "locale", loc.Serialize()) + ctx = metadata.AppendToOutgoingContext(ctx, MetadataKeyLocale, loc.Serialize()) } if token, ok := security.GetTokenFromContext(ctx); ok { - ctx = metadata.AppendToOutgoingContext(ctx, "bearer_token", token.GetValue()) + ctx = metadata.AppendToOutgoingContext(ctx, MetadataKeyBearerToken, token.GetValue()) } if reqID := log.RequestIDFromContext(ctx); reqID != "" { - ctx = metadata.AppendToOutgoingContext(ctx, "req_id", reqID) + ctx = metadata.AppendToOutgoingContext(ctx, MetadataKeyRequestID, reqID) } ctx = EncodeContextWithUTMData(ctx) + + if dep := middleware.ExternalDependencyContextFromContext(ctx); dep != nil { + ctx = metadata.AppendToOutgoingContext(ctx, MetadataKeyExternalDependencies, dep.String()) + } + return ctx } diff --git a/grpc/consts.go b/grpc/consts.go new file mode 100644 index 000000000..9646c21e9 --- /dev/null +++ b/grpc/consts.go @@ -0,0 +1,9 @@ +package grpc + +const ( + MetadataKeyBearerToken = "bearer_token" + MetadataKeyContentType = "content-type" + MetadataKeyExternalDependencies = "external_dependencies" + MetadataKeyLocale = "locale" + MetadataKeyRequestID = "req_id" +) diff --git a/grpc/server.go b/grpc/server.go index 223a2fbd9..99d9296d6 100644 --- a/grpc/server.go +++ b/grpc/server.go @@ -14,6 +14,7 @@ import ( grpc_prometheus "github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus" grpc_ctxtags "github.com/grpc-ecosystem/go-grpc-middleware/tags" grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing" + "github.com/pace/bricks/http/middleware" "github.com/pace/bricks/http/security" "github.com/pace/bricks/locale" "github.com/pace/bricks/maintenance/errors" @@ -151,7 +152,7 @@ func prepareContext(ctx context.Context) (context.Context, metadata.MD) { // add request context if req_id is given var reqID xid.ID - if ri := md.Get("req_id"); len(ri) > 0 { + if ri := md.Get(MetadataKeyRequestID); len(ri) > 0 { var err error reqID, err = xid.FromString(ri[0]) if err != nil { @@ -174,7 +175,7 @@ func prepareContext(ctx context.Context) (context.Context, metadata.MD) { }) // handle locale - if l := md.Get("locale"); len(l) > 0 { + if l := md.Get(MetadataKeyLocale); len(l) > 0 { loc, err := locale.ParseLocale(l[0]) if err != nil { log.Ctx(ctx).Debug().Err(err).Msgf("unable to parse locale: %v", err) @@ -186,13 +187,24 @@ func prepareContext(ctx context.Context) (context.Context, metadata.MD) { ctx = ContextWithUTMFromMetadata(ctx, md) // add security context if bearer token is given - if bt := md.Get("bearer_token"); len(bt) > 0 { + if bt := md.Get(MetadataKeyBearerToken); len(bt) > 0 { ctx = security.ContextWithToken(ctx, security.TokenString(bt[0])) } - delete(md, "content-type") - delete(md, "locale") - delete(md, "bearer_token") - delete(md, "req_id") + + // add external dependencies to context + externalDependencyContext := middleware.ExternalDependencyContext{} + + if externalDependencies := md.Get(MetadataKeyExternalDependencies); len(externalDependencies) > 0 { + externalDependencyContext.Parse(externalDependencies[0]) + } + + ctx = middleware.ContextWithExternalDependency(ctx, &externalDependencyContext) + + delete(md, MetadataKeyContentType) + delete(md, MetadataKeyLocale) + delete(md, MetadataKeyBearerToken) + delete(md, MetadataKeyRequestID) + delete(md, MetadataKeyExternalDependencies) return ctx, md } diff --git a/grpc/server_test.go b/grpc/server_test.go index e2d653205..a2bda5f50 100644 --- a/grpc/server_test.go +++ b/grpc/server_test.go @@ -7,9 +7,11 @@ import ( "context" "testing" + "github.com/pace/bricks/http/middleware" "github.com/pace/bricks/locale" "github.com/pace/bricks/maintenance/log" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "google.golang.org/grpc/metadata" ) @@ -29,14 +31,14 @@ func TestPrepareContext(t *testing.T) { // remote site is providing data using a bearer token ctx = metadata.NewIncomingContext(ctx, metadata.MD{ - "req_id": []string{"c690uu0ta2rv348epm8g"}, - "locale": []string{"fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5|Europe/Paris"}, - "bearer_token": []string{"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"}, + MetadataKeyRequestID: []string{"c690uu0ta2rv348epm8g"}, + MetadataKeyLocale: []string{"fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5|Europe/Paris"}, + MetadataKeyBearerToken: []string{"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"}, }) ctx1, md := prepareContext(ctx) - assert.Len(t, md.Get("req_id"), 0) - assert.Len(t, md.Get("bearer_token"), 0) + assert.Len(t, md.Get(MetadataKeyRequestID), 0) + assert.Len(t, md.Get(MetadataKeyBearerToken), 0) assert.Equal(t, "c690uu0ta2rv348epm8g", log.RequestIDFromContext(ctx1)) loc, ok := locale.FromCtx(ctx1) assert.True(t, ok) @@ -51,13 +53,13 @@ func TestPrepareContext(t *testing.T) { // remote site is providing data using a bearer token ctx = metadata.NewIncomingContext(ctx, metadata.MD{ - "req_id": []string{"c690uu0ta2rv348epm8g"}, - "bearer_token": []string{"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"}, + MetadataKeyRequestID: []string{"c690uu0ta2rv348epm8g"}, + MetadataKeyBearerToken: []string{"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"}, }) ctx2, md := prepareContext(ctx) - assert.Len(t, md.Get("req_id"), 0) - assert.Len(t, md.Get("bearer_token"), 0) + assert.Len(t, md.Get(MetadataKeyRequestID), 0) + assert.Len(t, md.Get(MetadataKeyBearerToken), 0) assert.Equal(t, "c690uu0ta2rv348epm8g", log.RequestIDFromContext(ctx1)) var buf2 bytes.Buffer @@ -67,4 +69,24 @@ func TestPrepareContext(t *testing.T) { assert.Contains(t, buf2.String(), ",\"message\":\"test\"}\n") _, ok = locale.FromCtx(ctx2) assert.False(t, ok) + + ctx = metadata.NewIncomingContext(ctx, metadata.MD{ + MetadataKeyExternalDependencies: []string{"foo:60000,bar:1000"}, + }) + + ctx3, md := prepareContext(ctx) + assert.Len(t, md.Get(MetadataKeyExternalDependencies), 0) + + externalDependencyContext := middleware.ExternalDependencyContextFromContext(ctx3) + require.NotNil(t, externalDependencyContext) + assert.Equal(t, "foo:60000,bar:1000", externalDependencyContext.String()) + + ctx = metadata.NewIncomingContext(context.Background(), metadata.MD{}) + + ctx4, md := prepareContext(ctx) + assert.Len(t, md.Get(MetadataKeyExternalDependencies), 0) + + externalDependencyContext = middleware.ExternalDependencyContextFromContext(ctx4) + require.NotNil(t, externalDependencyContext) + assert.Empty(t, externalDependencyContext.String()) } diff --git a/pkg/context/transfer.go b/pkg/context/transfer.go index 0d86c61a3..a4e122672 100755 --- a/pkg/context/transfer.go +++ b/pkg/context/transfer.go @@ -28,7 +28,10 @@ func Transfer(in context.Context) context.Context { out = utm.ContextTransfer(in, out) out = hlog.ContextTransfer(in, out) out = TransferTracingContext(in, out) - return locale.ContextTransfer(in, out) + out = locale.ContextTransfer(in, out) + out = TransferExternalDependencyContext(in, out) + + return out } func TransferTracingContext(in, out context.Context) context.Context {