@@ -103,8 +103,15 @@ export function instrumentFetchRequest(
103103
104104/**
105105 * Adds sentry-trace and baggage headers to the various forms of fetch headers.
106+ * exported only for testing purposes
107+ *
108+ * When we determine if we should add a baggage header, there are 3 cases:
109+ * 1. No previous baggage header -> add baggage
110+ * 2. Previous baggage header has no sentry baggage values -> add our baggage
111+ * 3. Previous baggage header has sentry baggage values -> do nothing (might have been added manually by users)
106112 */
107- function _addTracingHeadersToFetchRequest (
113+ // eslint-disable-next-line complexity -- yup it's this complicated :(
114+ export function _addTracingHeadersToFetchRequest (
108115 request : string | Request ,
109116 fetchOptionsObj : {
110117 headers ?:
@@ -124,78 +131,70 @@ function _addTracingHeadersToFetchRequest(
124131 return undefined ;
125132 }
126133
127- const headers = fetchOptionsObj . headers || ( isRequest ( request ) ? request . headers : undefined ) ;
134+ const originalHeaders = fetchOptionsObj . headers || ( isRequest ( request ) ? request . headers : undefined ) ;
128135
129- if ( ! headers ) {
136+ if ( ! originalHeaders ) {
130137 return { ...traceHeaders } ;
131- } else if ( isHeaders ( headers ) ) {
132- const newHeaders = new Headers ( headers ) ;
133- newHeaders . set ( 'sentry-trace' , sentryTrace ) ;
138+ } else if ( isHeaders ( originalHeaders ) ) {
139+ const newHeaders = new Headers ( originalHeaders ) ;
140+
141+ // We don't want to override manually added sentry headers
142+ if ( ! newHeaders . get ( 'sentry-trace' ) ) {
143+ newHeaders . set ( 'sentry-trace' , sentryTrace ) ;
144+ }
134145
135146 if ( baggage ) {
136147 const prevBaggageHeader = newHeaders . get ( 'baggage' ) ;
137- if ( prevBaggageHeader ) {
138- const prevHeaderStrippedFromSentryBaggage = stripBaggageHeaderOfSentryBaggageValues ( prevBaggageHeader ) ;
139- newHeaders . set (
140- 'baggage' ,
141- // If there are non-sentry entries (i.e. if the stripped string is non-empty/truthy) combine the stripped header and sentry baggage header
142- // otherwise just set the sentry baggage header
143- prevHeaderStrippedFromSentryBaggage ? `${ prevHeaderStrippedFromSentryBaggage } ,${ baggage } ` : baggage ,
144- ) ;
145- } else {
148+
149+ if ( ! prevBaggageHeader ) {
146150 newHeaders . set ( 'baggage' , baggage ) ;
151+ } else if ( ! baggageHeaderHasSentryBaggageValues ( prevBaggageHeader ) ) {
152+ newHeaders . set ( 'baggage' , `${ prevBaggageHeader } ,${ baggage } ` ) ;
147153 }
148154 }
149155
150156 return newHeaders ;
151- } else if ( Array . isArray ( headers ) ) {
152- const newHeaders = [
153- ...headers
154- // Remove any existing sentry-trace headers
155- . filter ( header => {
156- return ! ( Array . isArray ( header ) && header [ 0 ] === 'sentry-trace' ) ;
157- } )
158- // Get rid of previous sentry baggage values in baggage header
159- . map ( header => {
160- if ( Array . isArray ( header ) && header [ 0 ] === 'baggage' && typeof header [ 1 ] === 'string' ) {
161- const [ headerName , headerValue , ...rest ] = header ;
162- return [ headerName , stripBaggageHeaderOfSentryBaggageValues ( headerValue ) , ...rest ] ;
163- } else {
164- return header ;
165- }
166- } ) ,
167- // Attach the new sentry-trace header
168- [ 'sentry-trace' , sentryTrace ] ,
169- ] ;
157+ } else if ( Array . isArray ( originalHeaders ) ) {
158+ const newHeaders = [ ...originalHeaders ] ;
170159
171- if ( baggage ) {
160+ if ( ! originalHeaders . find ( header => header [ 0 ] === 'sentry-trace' ) ) {
161+ newHeaders . push ( [ 'sentry-trace' , sentryTrace ] ) ;
162+ }
163+
164+ const prevBaggageHeaderWithSentryValues = originalHeaders . find (
165+ header => header [ 0 ] === 'baggage' && baggageHeaderHasSentryBaggageValues ( header [ 1 ] ) ,
166+ ) ;
167+
168+ if ( baggage && ! prevBaggageHeaderWithSentryValues ) {
172169 // If there are multiple entries with the same key, the browser will merge the values into a single request header.
173170 // Its therefore safe to simply push a "baggage" entry, even though there might already be another baggage header.
174171 newHeaders . push ( [ 'baggage' , baggage ] ) ;
175172 }
176173
177174 return newHeaders as PolymorphicRequestHeaders ;
178175 } else {
179- const existingBaggageHeader = 'baggage' in headers ? headers . baggage : undefined ;
180- let newBaggageHeaders : string [ ] = [ ] ;
181-
182- if ( Array . isArray ( existingBaggageHeader ) ) {
183- newBaggageHeaders = existingBaggageHeader
184- . map ( headerItem =>
185- typeof headerItem === 'string' ? stripBaggageHeaderOfSentryBaggageValues ( headerItem ) : headerItem ,
186- )
187- . filter ( headerItem => headerItem === '' ) ;
188- } else if ( existingBaggageHeader ) {
189- newBaggageHeaders . push ( stripBaggageHeaderOfSentryBaggageValues ( existingBaggageHeader ) ) ;
190- }
191-
192- if ( baggage ) {
176+ const existingSentryTraceHeader = 'sentry-trace' in originalHeaders ? originalHeaders [ 'sentry-trace' ] : undefined ;
177+
178+ const existingBaggageHeader = 'baggage' in originalHeaders ? originalHeaders . baggage : undefined ;
179+ const newBaggageHeaders : string [ ] = existingBaggageHeader
180+ ? Array . isArray ( existingBaggageHeader )
181+ ? [ ...existingBaggageHeader ]
182+ : [ existingBaggageHeader ]
183+ : [ ] ;
184+
185+ const prevBaggageHeaderWithSentryValues =
186+ existingBaggageHeader &&
187+ ( Array . isArray ( existingBaggageHeader )
188+ ? existingBaggageHeader . find ( headerItem => baggageHeaderHasSentryBaggageValues ( headerItem ) )
189+ : baggageHeaderHasSentryBaggageValues ( existingBaggageHeader ) ) ;
190+
191+ if ( baggage && ! prevBaggageHeaderWithSentryValues ) {
193192 newBaggageHeaders . push ( baggage ) ;
194193 }
195194
196195 return {
197- ...( headers as Exclude < typeof headers , Headers > ) ,
198- 'sentry-trace' : sentryTrace ,
196+ ...( originalHeaders as Exclude < typeof originalHeaders , Headers > ) ,
197+ 'sentry-trace' : ( existingSentryTraceHeader as string | undefined ) ?? sentryTrace ,
199198 baggage : newBaggageHeaders . length > 0 ? newBaggageHeaders . join ( ',' ) : undefined ,
200199 } ;
201200 }
@@ -219,14 +218,8 @@ function endSpan(span: Span, handlerData: HandlerDataFetch): void {
219218 span . end ( ) ;
220219}
221220
222- function stripBaggageHeaderOfSentryBaggageValues ( baggageHeader : string ) : string {
223- return (
224- baggageHeader
225- . split ( ',' )
226- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
227- . filter ( baggageEntry => ! baggageEntry . split ( '=' ) [ 0 ] ! . startsWith ( SENTRY_BAGGAGE_KEY_PREFIX ) )
228- . join ( ',' )
229- ) ;
221+ function baggageHeaderHasSentryBaggageValues ( baggageHeader : string ) : boolean {
222+ return baggageHeader . split ( ',' ) . some ( baggageEntry => baggageEntry . trim ( ) . startsWith ( SENTRY_BAGGAGE_KEY_PREFIX ) ) ;
230223}
231224
232225function isHeaders ( headers : unknown ) : headers is Headers {
0 commit comments