11import { captureEvent , getCurrentHub } from '@sentry/core' ;
22import { Event as SentryEvent , Integration } from '@sentry/types' ;
3- import { addExceptionMechanism , fill , GLOBAL_OBJ , logger } from '@sentry/utils' ;
3+ import { addExceptionMechanism , fill , GLOBAL_OBJ , logger , supportsNativeFetch } from '@sentry/utils' ;
44
55import { eventFromUnknownInput } from '../eventbuilder' ;
66
77export type HttpStatusCodeRange = [ number , number ] | number ;
88export type HttpRequestTarget = string | RegExp ;
9-
109interface HttpClientOptions {
10+ /**
11+ * Controls whether failed requests should be captured.
12+ *
13+ * Default: false
14+ */
1115 captureFailedRequests ?: boolean ;
16+
17+ /**
18+ * HTTP status codes that should be considered failed.
19+ * This array can contain tuples of `[begin, end]` (both inclusive),
20+ * single status codes, or a combinations of both
21+ *
22+ * Example: [[500, 505], 507]
23+ * Default: [[500, 599]]
24+ */
1225 failedRequestStatusCodes ?: HttpStatusCodeRange [ ] ;
26+
27+ /**
28+ * Targets to track for failed requests.
29+ * This array can contain strings or regular expressions.
30+ *
31+ * Example: ['http://localhost', /api\/.*\/]
32+ * Default: [/.*\/]
33+ */
1334 failedRequestTargets ?: HttpRequestTarget [ ] ;
1435}
1536
@@ -65,7 +86,6 @@ export class HttpClient implements Integration {
6586 private _fetchResponseHandler ( requestInfo : RequestInfo , response : Response , requestInit ?: RequestInit ) : void {
6687 if ( this . _shouldCaptureResponse ( response . status , response . url ) ) {
6788 const request = new Request ( requestInfo , requestInit ) ;
68- const url = new URL ( request . url ) ;
6989
7090 let requestHeaders , responseHeaders , requestCookies , responseCookies ;
7191
@@ -96,7 +116,7 @@ export class HttpClient implements Integration {
96116 }
97117
98118 const event = this . _createEvent ( {
99- url : url ,
119+ url : request . url ,
100120 method : request . method ,
101121 status : response . status ,
102122 requestHeaders,
@@ -105,12 +125,7 @@ export class HttpClient implements Integration {
105125 responseCookies,
106126 } ) ;
107127
108- captureEvent ( event , {
109- data : {
110- OK_HTTP_REQUEST : request ,
111- OK_HTTP_RESPONSE : response ,
112- } ,
113- } ) ;
128+ captureEvent ( event ) ;
114129 }
115130 }
116131
@@ -123,8 +138,6 @@ export class HttpClient implements Integration {
123138 */
124139 private _xhrResponseHandler ( xhr : XMLHttpRequest , method : string , headers : Record < string , string > ) : void {
125140 if ( this . _shouldCaptureResponse ( xhr . status , xhr . responseURL ) ) {
126- const url = new URL ( xhr . responseURL ) ;
127-
128141 let requestHeaders , responseCookies , responseHeaders ;
129142
130143 if ( getCurrentHub ( ) . shouldSendDefaultPii ( ) ) {
@@ -148,7 +161,7 @@ export class HttpClient implements Integration {
148161 }
149162
150163 const event = this . _createEvent ( {
151- url : url ,
164+ url : xhr . responseURL ,
152165 method : method ,
153166 status : xhr . status ,
154167 requestHeaders,
@@ -274,34 +287,30 @@ export class HttpClient implements Integration {
274287 *
275288 */
276289 private _wrapFetch ( ) : void {
277- if ( ! ( 'fetch' in GLOBAL_OBJ ) ) {
290+ if ( ! supportsNativeFetch ( ) ) {
278291 return ;
279292 }
280293
281294 // eslint-disable-next-line @typescript-eslint/no-this-alias
282295 const self = this ;
283296
284- fill (
285- GLOBAL_OBJ ,
286- 'fetch' ,
287- function ( originalFetch : ( requestInfo : RequestInfo , requestInit ?: RequestInit ) => Promise < Response > ) {
288- return function ( this : Window , requestInfo : RequestInfo , requestInit ?: RequestInit ) : Promise < Response > {
289- const responsePromise : Promise < Response > = originalFetch . apply ( this , [ requestInfo , requestInit ] ) ;
290-
291- responsePromise
292- . then ( ( response : Response ) => {
293- self . _fetchResponseHandler ( requestInfo , response , requestInit ) ;
294- return response ;
295- } )
296- . catch ( ( error : Error ) => {
297- // TODO:
298- throw error ;
299- } ) ;
300-
301- return responsePromise ;
302- } ;
303- } ,
304- ) ;
297+ fill ( GLOBAL_OBJ , 'fetch' , function ( originalFetch : ( ...args : unknown [ ] ) => Promise < Response > ) {
298+ return function ( this : Window , ...args : unknown [ ] ) : Promise < Response > {
299+ const [ requestInfo , requestInit ] = args as [ RequestInfo , RequestInit | undefined ] ;
300+ const responsePromise : Promise < Response > = originalFetch . apply ( this , args ) ;
301+
302+ responsePromise
303+ . then ( ( response : Response ) => {
304+ self . _fetchResponseHandler ( requestInfo , response , requestInit ) ;
305+ return response ;
306+ } )
307+ . catch ( ( error : Error ) => {
308+ throw error ;
309+ } ) ;
310+
311+ return responsePromise ;
312+ } ;
313+ } ) ;
305314 }
306315
307316 /**
@@ -315,11 +324,11 @@ export class HttpClient implements Integration {
315324 // eslint-disable-next-line @typescript-eslint/no-this-alias
316325 const self = this ;
317326
318- fill ( XMLHttpRequest . prototype , 'open' , function ( originalOpen : ( method : string ) => void ) : ( ) => void {
319- return function ( this : XMLHttpRequest , ...openArgs : any [ ] ) : void {
327+ fill ( XMLHttpRequest . prototype , 'open' , function ( originalOpen : ( ... openArgs : unknown [ ] ) => void ) : ( ) => void {
328+ return function ( this : XMLHttpRequest , ...openArgs : unknown [ ] ) : void {
320329 // eslint-disable-next-line @typescript-eslint/no-this-alias
321330 const xhr = this ;
322- const method = openArgs [ 0 ] ;
331+ const method = openArgs [ 0 ] as string ;
323332 const headers : Record < string , string > = { } ;
324333
325334 // Intercepting `setRequestHeader` to access the request headers of XHR instance.
@@ -329,25 +338,27 @@ export class HttpClient implements Integration {
329338 xhr ,
330339 'setRequestHeader' ,
331340 // eslint-disable-next-line @typescript-eslint/ban-types
332- function ( originalSetRequestHeader : ( header : string , value : string ) => void ) : Function {
333- return function ( header : string , value : string ) : void {
341+ function ( originalSetRequestHeader : ( ...setRequestHeaderArgs : unknown [ ] ) => void ) : Function {
342+ return function ( ...setRequestHeaderArgs : unknown [ ] ) : void {
343+ const [ header , value ] = setRequestHeaderArgs as [ string , string ] ;
344+
334345 headers [ header ] = value ;
335346
336- return originalSetRequestHeader . apply ( xhr , [ header , value ] ) ;
347+ return originalSetRequestHeader . apply ( xhr , setRequestHeaderArgs ) ;
337348 } ;
338349 } ,
339350 ) ;
340351
341352 // eslint-disable-next-line @typescript-eslint/ban-types
342- fill ( xhr , 'onloadend' , function ( original ?: ( progressEvent : ProgressEvent ) => void ) : Function {
343- return function ( progressEvent : ProgressEvent ) : void {
353+ fill ( xhr , 'onloadend' , function ( original ?: ( ... onloadendArgs : unknown [ ] ) => void ) : Function {
354+ return function ( ... onloadendArgs : unknown [ ] ) : void {
344355 try {
345356 self . _xhrResponseHandler ( xhr , method , headers ) ;
346357 } catch ( e ) {
347358 __DEBUG_BUILD__ && logger . warn ( 'Error while extracting response event form XHR response' , e ) ;
348359 }
349360
350- return original ?. apply ( xhr , progressEvent ) ;
361+ return original ?. apply ( xhr , onloadendArgs ) ;
351362 } ;
352363 } ) ;
353364
@@ -383,7 +394,7 @@ export class HttpClient implements Integration {
383394 * @returns event
384395 */
385396 private _createEvent ( data : {
386- url : URL ;
397+ url : string ;
387398 method : string ;
388399 status : number ;
389400 responseHeaders ?: Record < string , string > ;
@@ -394,10 +405,7 @@ export class HttpClient implements Integration {
394405 const event = eventFromUnknownInput ( ( ) => [ ] , `HTTP Client Error with status code: ${ data . status } ` ) ;
395406
396407 event . request = {
397- url : data . url . href ,
398- query_string : data . url . search ,
399- // TODO: should we add `data: request.body` too?
400- // https://develop.sentry.dev/sdk/event-payloads/request/
408+ url : data . url ,
401409 method : data . method ,
402410 headers : data . requestHeaders ,
403411 cookies : data . requestCookies ,
0 commit comments