From 92cd58374932bc6e83f00abc9feb50c2d6896fb7 Mon Sep 17 00:00:00 2001 From: Thomas Hipp Date: Thu, 29 Aug 2024 11:26:13 +0200 Subject: [PATCH 1/4] grpc: Add external dependencies to context --- grpc/client.go | 6 ++++++ grpc/consts.go | 5 +++++ grpc/server.go | 12 ++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 grpc/consts.go diff --git a/grpc/client.go b/grpc/client.go index 210c835d1..3cd2ed523 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" @@ -81,5 +82,10 @@ func prepareClientContext(ctx context.Context) context.Context { ctx = metadata.AppendToOutgoingContext(ctx, "req_id", 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..8f5f72732 --- /dev/null +++ b/grpc/consts.go @@ -0,0 +1,5 @@ +package grpc + +const ( + MetadataKeyExternalDependencies = "external_dependencies" +) diff --git a/grpc/server.go b/grpc/server.go index 223a2fbd9..2773c32a6 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" @@ -189,10 +190,21 @@ func prepareContext(ctx context.Context) (context.Context, metadata.MD) { if bt := md.Get("bearer_token"); len(bt) > 0 { ctx = security.ContextWithToken(ctx, security.TokenString(bt[0])) } + + // 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, "content-type") delete(md, "locale") delete(md, "bearer_token") delete(md, "req_id") + delete(md, MetadataKeyExternalDependencies) return ctx, md } From 6dc008546beca767d2e6aa5e5ce1cfb38108b89b Mon Sep 17 00:00:00 2001 From: Thomas Hipp Date: Thu, 29 Aug 2024 11:31:39 +0200 Subject: [PATCH 2/4] grpc: Use constants for metadata keys --- grpc/client.go | 6 +++--- grpc/consts.go | 4 ++++ grpc/server.go | 14 +++++++------- grpc/server_test.go | 19 ++++++++++--------- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/grpc/client.go b/grpc/client.go index 3cd2ed523..43824b3f1 100644 --- a/grpc/client.go +++ b/grpc/client.go @@ -73,13 +73,13 @@ 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) diff --git a/grpc/consts.go b/grpc/consts.go index 8f5f72732..9646c21e9 100644 --- a/grpc/consts.go +++ b/grpc/consts.go @@ -1,5 +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 2773c32a6..99d9296d6 100644 --- a/grpc/server.go +++ b/grpc/server.go @@ -152,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 { @@ -175,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) @@ -187,7 +187,7 @@ 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])) } @@ -200,10 +200,10 @@ func prepareContext(ctx context.Context) (context.Context, metadata.MD) { ctx = middleware.ContextWithExternalDependency(ctx, &externalDependencyContext) - delete(md, "content-type") - delete(md, "locale") - delete(md, "bearer_token") - delete(md, "req_id") + 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..ce918a86e 100644 --- a/grpc/server_test.go +++ b/grpc/server_test.go @@ -29,14 +29,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 +51,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 +67,5 @@ func TestPrepareContext(t *testing.T) { assert.Contains(t, buf2.String(), ",\"message\":\"test\"}\n") _, ok = locale.FromCtx(ctx2) assert.False(t, ok) + } From fe6659e85394fddef4933cedccc82c8b6121579b Mon Sep 17 00:00:00 2001 From: Thomas Hipp Date: Thu, 29 Aug 2024 12:15:26 +0200 Subject: [PATCH 3/4] grpc: Add test for external dependencies --- grpc/server_test.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/grpc/server_test.go b/grpc/server_test.go index ce918a86e..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" ) @@ -68,4 +70,23 @@ func TestPrepareContext(t *testing.T) { _, 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()) } From 3503b4c29154b29c5ad9994c3274c24e595780ac Mon Sep 17 00:00:00 2001 From: Thomas Hipp Date: Fri, 30 Aug 2024 08:03:53 +0200 Subject: [PATCH 4/4] pkg/context: Transfer external dependency context --- pkg/context/transfer.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 {