@@ -265,6 +265,85 @@ describe('metadata propagation (gRPC and HTTP)', () => {
265265 } ) ;
266266 } ) ;
267267
268+ it ( 'does not mutate shared HTTP/REST plain object metadata across calls' , done => {
269+ const sharedMetadata : Record < string , unknown > = {
270+ 'x-goog-api-client' : [ 'grpc-web/1.0' ] ,
271+ } ;
272+
273+ const tracer = trace . getTracer ( 'test-tracer' ) ;
274+ const span1 = tracer . startSpan ( 'http-rpc-1' ) ;
275+ const span2 = tracer . startSpan ( 'http-rpc-2' ) ;
276+
277+ let metadataCall1 : Record < string , unknown > | null = null ;
278+ let metadataCall2 : Record < string , unknown > | null = null ;
279+
280+ const stub1 = (
281+ arg : { } ,
282+ meta : { } ,
283+ opt : { } ,
284+ cb : Function ,
285+ ) : GRPCCallResult => {
286+ metadataCall1 = meta as Record < string , unknown > ;
287+ cb ( null , { } ) ;
288+ return { } as GRPCCallResult ;
289+ } ;
290+
291+ const stub2 = (
292+ arg : { } ,
293+ meta : { } ,
294+ opt : { } ,
295+ cb : Function ,
296+ ) : GRPCCallResult => {
297+ metadataCall2 = meta as Record < string , unknown > ;
298+ cb ( null , { } ) ;
299+ return { } as GRPCCallResult ;
300+ } ;
301+
302+ const otherArgs : GRPCCallOtherArgs = {
303+ metadataBuilder : ( ) => sharedMetadata ,
304+ } ;
305+
306+ const handler1 = addTimeoutArg (
307+ stub1 as unknown as GRPCCall ,
308+ 1000 ,
309+ otherArgs ,
310+ ) ;
311+ const handler2 = addTimeoutArg (
312+ stub2 as unknown as GRPCCall ,
313+ 1000 ,
314+ otherArgs ,
315+ ) ;
316+
317+ context . with ( trace . setSpan ( context . active ( ) , span1 ) , ( ) => {
318+ handler1 ( { } , ( ) => {
319+ span1 . end ( ) ;
320+
321+ context . with ( trace . setSpan ( context . active ( ) , span2 ) , ( ) => {
322+ handler2 ( { } , ( ) => {
323+ span2 . end ( ) ;
324+
325+ const spanCtx1 = span1 . spanContext ( ) ;
326+ assert . strictEqual (
327+ metadataCall1 ! [ 'traceparent' ] ,
328+ `00-${ spanCtx1 . traceId } -${ spanCtx1 . spanId } -0${ spanCtx1 . traceFlags } ` ,
329+ ) ;
330+
331+ const spanCtx2 = span2 . spanContext ( ) ;
332+ assert . strictEqual (
333+ metadataCall2 ! [ 'traceparent' ] ,
334+ `00-${ spanCtx2 . traceId } -${ spanCtx2 . spanId } -0${ spanCtx2 . traceFlags } ` ,
335+ ) ;
336+
337+ assert . notStrictEqual ( metadataCall1 , sharedMetadata ) ;
338+ assert . notStrictEqual ( metadataCall2 , sharedMetadata ) ;
339+ assert . strictEqual ( sharedMetadata [ 'traceparent' ] , undefined ) ;
340+ done ( ) ;
341+ } ) ;
342+ } ) ;
343+ } ) ;
344+ } ) ;
345+ } ) ;
346+
268347 it ( 'does not inject into gRPC or HTTP metadata when telemetry is disabled' , done => {
269348 delete process . env . GOOGLE_SDK_NODE_ENABLE_TRACING ;
270349
0 commit comments