@@ -14,6 +14,7 @@ import (
1414 "github.com/tidwall/gjson"
1515 "google.golang.org/grpc"
1616 "google.golang.org/grpc/credentials/insecure"
17+ "google.golang.org/grpc/metadata"
1718 "google.golang.org/grpc/test/bufconn"
1819 "google.golang.org/protobuf/encoding/protojson"
1920 protoref "google.golang.org/protobuf/reflect/protoreflect"
@@ -5445,3 +5446,69 @@ func Test_Datasource_Load_WithHeaders(t *testing.T) {
54455446 })
54465447 }
54475448}
5449+
5450+ func Test_Datasource_Load_PreservesExistingContextMetadata (t * testing.T ) {
5451+ conn , cleanup := setupTestGRPCServer (t )
5452+ t .Cleanup (cleanup )
5453+
5454+ type graphqlError struct {
5455+ Message string `json:"message"`
5456+ }
5457+ type graphqlResponse struct {
5458+ Data map [string ]interface {} `json:"data"`
5459+ Errors []graphqlError `json:"errors,omitempty"`
5460+ }
5461+
5462+ // Parse the GraphQL schema
5463+ schemaDoc := grpctest .MustGraphQLSchema (t )
5464+
5465+ query := `query UserQuery($id: ID!) { user(id: $id) { id name } }`
5466+ vars := `{"variables":{"id":"test-user-123"}}`
5467+
5468+ // Parse the GraphQL query
5469+ queryDoc , report := astparser .ParseGraphqlDocumentString (query )
5470+ require .False (t , report .HasErrors (), "failed to parse query: %s" , report .Error ())
5471+
5472+ compiler , err := NewProtoCompiler (grpctest .MustProtoSchema (t ), testMapping ())
5473+ require .NoError (t , err )
5474+
5475+ // Create the datasource
5476+ ds , err := NewDataSource (conn , DataSourceConfig {
5477+ Operation : & queryDoc ,
5478+ Definition : & schemaDoc ,
5479+ SubgraphName : "Products" ,
5480+ Mapping : testMapping (),
5481+ Compiler : compiler ,
5482+ })
5483+ require .NoError (t , err )
5484+
5485+ // Create a context with existing metadata
5486+ ctx := metadata .NewOutgoingContext (
5487+ context .Background (),
5488+ metadata .Pairs ("x-existing-key" , "existing-value" ),
5489+ )
5490+
5491+ // Create HTTP headers to be forwarded
5492+ headers := make (http.Header )
5493+ headers .Set ("X-User-ID" , "header-user-456" )
5494+
5495+ // Execute the query with both existing context metadata and new HTTP headers
5496+ input := fmt .Sprintf (`{"query":%q,"body":%s}` , query , vars )
5497+ output , err := ds .Load (ctx , headers , []byte (input ))
5498+ require .NoError (t , err )
5499+
5500+ // Parse the response
5501+ var resp graphqlResponse
5502+ err = json .Unmarshal (output , & resp )
5503+ require .NoError (t , err , "Failed to unmarshal response" )
5504+
5505+ // Verify no errors
5506+ require .Empty (t , resp .Errors , "Should not have GraphQL errors" )
5507+
5508+ // Verify the response includes both the header-derived ID and the existing metadata value
5509+ user , ok := resp .Data ["user" ].(map [string ]interface {})
5510+ require .True (t , ok , "user should be an object" )
5511+ require .Equal (t , "header-user-456" , user ["id" ], "user ID should come from HTTP header" )
5512+ require .Equal (t , "User header-user-456 (existing: existing-value)" , user ["name" ],
5513+ "user name should include both header-derived ID and existing context metadata" )
5514+ }
0 commit comments