@@ -103,8 +103,10 @@ export function instrumentFetchRequest(
103
103
104
104
/**
105
105
* Adds sentry-trace and baggage headers to the various forms of fetch headers.
106
+ * exported only for testing purposes
106
107
*/
107
- function _addTracingHeadersToFetchRequest (
108
+ // eslint-disable-next-line complexity -- yup it's this complicated :(
109
+ export function _addTracingHeadersToFetchRequest (
108
110
request : string | Request ,
109
111
fetchOptionsObj : {
110
112
headers ?:
@@ -124,78 +126,74 @@ function _addTracingHeadersToFetchRequest(
124
126
return undefined ;
125
127
}
126
128
127
- const headers = fetchOptionsObj . headers || ( isRequest ( request ) ? request . headers : undefined ) ;
129
+ const originalHeaders = fetchOptionsObj . headers || ( isRequest ( request ) ? request . headers : undefined ) ;
128
130
129
- if ( ! headers ) {
131
+ if ( ! originalHeaders ) {
130
132
return { ...traceHeaders } ;
131
- } else if ( isHeaders ( headers ) ) {
132
- const newHeaders = new Headers ( headers ) ;
133
- newHeaders . set ( 'sentry-trace' , sentryTrace ) ;
133
+ } else if ( isHeaders ( originalHeaders ) ) {
134
+ const newHeaders = new Headers ( originalHeaders ) ;
135
+
136
+ // We don't want to override manually added sentry headers
137
+ if ( ! newHeaders . get ( 'sentry-trace' ) ) {
138
+ newHeaders . set ( 'sentry-trace' , sentryTrace ) ;
139
+ }
134
140
135
141
if ( baggage ) {
136
142
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 {
143
+
144
+ // 3 cases:
145
+ // 1. No previous baggage header -> add baggage
146
+ // 2. Previous baggage header has no sentry baggage values -> add our baggage
147
+ // 3. Previous baggage header has sentry baggage values -> do nothing (might have been added manually by users)
148
+ if ( ! prevBaggageHeader ) {
146
149
newHeaders . set ( 'baggage' , baggage ) ;
150
+ } else if ( ! baggageHeaderHasSentryBaggageValues ( prevBaggageHeader ) ) {
151
+ newHeaders . set ( 'baggage' , `${ prevBaggageHeader } ,${ baggage } ` ) ;
147
152
}
148
153
}
149
154
150
155
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
- ] ;
156
+ } else if ( Array . isArray ( originalHeaders ) ) {
157
+ const newHeaders = [ ...originalHeaders ] ;
170
158
171
- if ( baggage ) {
159
+ if ( ! originalHeaders . find ( header => header [ 0 ] === 'sentry-trace' ) ) {
160
+ newHeaders . push ( [ 'sentry-trace' , sentryTrace ] ) ;
161
+ }
162
+
163
+ const prevBaggageHeaderWithSentryValues = originalHeaders . find (
164
+ header => header [ 0 ] === 'baggage' && baggageHeaderHasSentryBaggageValues ( header [ 1 ] ) ,
165
+ ) ;
166
+
167
+ if ( baggage && ! prevBaggageHeaderWithSentryValues ) {
172
168
// If there are multiple entries with the same key, the browser will merge the values into a single request header.
173
169
// Its therefore safe to simply push a "baggage" entry, even though there might already be another baggage header.
174
170
newHeaders . push ( [ 'baggage' , baggage ] ) ;
175
171
}
176
172
177
173
return newHeaders as PolymorphicRequestHeaders ;
178
174
} 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 ) {
175
+ const existingSentryTraceHeader = 'sentry-trace' in originalHeaders ? originalHeaders [ 'sentry-trace' ] : undefined ;
176
+
177
+ const existingBaggageHeader = 'baggage' in originalHeaders ? originalHeaders . baggage : undefined ;
178
+ const newBaggageHeaders : string [ ] = existingBaggageHeader
179
+ ? Array . isArray ( existingBaggageHeader )
180
+ ? [ ...existingBaggageHeader ]
181
+ : [ existingBaggageHeader ]
182
+ : [ ] ;
183
+
184
+ const prevBaggageHeaderWithSentryValues =
185
+ existingBaggageHeader &&
186
+ ( Array . isArray ( existingBaggageHeader )
187
+ ? existingBaggageHeader . find ( headerItem => baggageHeaderHasSentryBaggageValues ( headerItem ) )
188
+ : baggageHeaderHasSentryBaggageValues ( existingBaggageHeader ) ) ;
189
+
190
+ if ( baggage && ! prevBaggageHeaderWithSentryValues ) {
193
191
newBaggageHeaders . push ( baggage ) ;
194
192
}
195
193
196
194
return {
197
- ...( headers as Exclude < typeof headers , Headers > ) ,
198
- 'sentry-trace' : sentryTrace ,
195
+ ...( originalHeaders as Exclude < typeof originalHeaders , Headers > ) ,
196
+ 'sentry-trace' : ( existingSentryTraceHeader as string | undefined ) ?? sentryTrace ,
199
197
baggage : newBaggageHeaders . length > 0 ? newBaggageHeaders . join ( ',' ) : undefined ,
200
198
} ;
201
199
}
@@ -219,14 +217,10 @@ function endSpan(span: Span, handlerData: HandlerDataFetch): void {
219
217
span . end ( ) ;
220
218
}
221
219
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
- ) ;
220
+ function baggageHeaderHasSentryBaggageValues ( baggageHeader : string ) : boolean {
221
+ return baggageHeader
222
+ . split ( ',' )
223
+ . some ( baggageEntry => baggageEntry . split ( '=' ) [ 0 ] ?. startsWith ( SENTRY_BAGGAGE_KEY_PREFIX ) ) ;
230
224
}
231
225
232
226
function isHeaders ( headers : unknown ) : headers is Headers {
0 commit comments