@@ -103,8 +103,15 @@ 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
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)
106
112
*/
107
- function _addTracingHeadersToFetchRequest (
113
+ // eslint-disable-next-line complexity -- yup it's this complicated :(
114
+ export function _addTracingHeadersToFetchRequest (
108
115
request : string | Request ,
109
116
fetchOptionsObj : {
110
117
headers ?:
@@ -124,78 +131,70 @@ function _addTracingHeadersToFetchRequest(
124
131
return undefined ;
125
132
}
126
133
127
- const headers = fetchOptionsObj . headers || ( isRequest ( request ) ? request . headers : undefined ) ;
134
+ const originalHeaders = fetchOptionsObj . headers || ( isRequest ( request ) ? request . headers : undefined ) ;
128
135
129
- if ( ! headers ) {
136
+ if ( ! originalHeaders ) {
130
137
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
+ }
134
145
135
146
if ( baggage ) {
136
147
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 ) {
146
150
newHeaders . set ( 'baggage' , baggage ) ;
151
+ } else if ( ! baggageHeaderHasSentryBaggageValues ( prevBaggageHeader ) ) {
152
+ newHeaders . set ( 'baggage' , `${ prevBaggageHeader } ,${ baggage } ` ) ;
147
153
}
148
154
}
149
155
150
156
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 ] ;
170
159
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 ) {
172
169
// If there are multiple entries with the same key, the browser will merge the values into a single request header.
173
170
// Its therefore safe to simply push a "baggage" entry, even though there might already be another baggage header.
174
171
newHeaders . push ( [ 'baggage' , baggage ] ) ;
175
172
}
176
173
177
174
return newHeaders as PolymorphicRequestHeaders ;
178
175
} 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 ) {
193
192
newBaggageHeaders . push ( baggage ) ;
194
193
}
195
194
196
195
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 ,
199
198
baggage : newBaggageHeaders . length > 0 ? newBaggageHeaders . join ( ',' ) : undefined ,
200
199
} ;
201
200
}
@@ -219,14 +218,8 @@ function endSpan(span: Span, handlerData: HandlerDataFetch): void {
219
218
span . end ( ) ;
220
219
}
221
220
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 ) ) ;
230
223
}
231
224
232
225
function isHeaders ( headers : unknown ) : headers is Headers {
0 commit comments