1+ /* eslint-disable complexity */
12import { getClient } from './currentScopes' ;
23import { SEMANTIC_ATTRIBUTE_SENTRY_OP , SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from './semanticAttributes' ;
34import { SPAN_STATUS_ERROR , setHttpStatus , startInactiveSpan } from './tracing' ;
45import { SentryNonRecordingSpan } from './tracing/sentryNonRecordingSpan' ;
56import type { FetchBreadcrumbHint , HandlerDataFetch , Span , SpanOrigin } from './types-hoist' ;
67import { SENTRY_BAGGAGE_KEY_PREFIX } from './utils-hoist/baggage' ;
78import { isInstanceOf } from './utils-hoist/is' ;
8- import { parseUrl , stripUrlQueryAndFragment } from './utils-hoist/url' ;
9+ import { parseStringToURL , stripUrlQueryAndFragment } from './utils-hoist/url' ;
910import { hasSpansEnabled } from './utils/hasSpansEnabled' ;
1011import { getActiveSpan } from './utils/spanUtils' ;
1112import { getTraceData } from './utils/traceData' ;
@@ -53,8 +54,20 @@ export function instrumentFetchRequest(
5354 return undefined ;
5455 }
5556
56- const fullUrl = getFullURL ( url ) ;
57- const parsedUrl = fullUrl ? parseUrl ( fullUrl ) : parseUrl ( url ) ;
57+ // Curious about `thismessage:/`? See: https://www.rfc-editor.org/rfc/rfc2557.html
58+ // > When the methods above do not yield an absolute URI, a base URL
59+ // > of "thismessage:/" MUST be employed. This base URL has been
60+ // > defined for the sole purpose of resolving relative references
61+ // > within a multipart/related structure when no other base URI is
62+ // > specified.
63+ //
64+ // We need to provide a base URL to `parseStringToURL` because the fetch API gives us a
65+ // relative URL sometimes.
66+ //
67+ // This is the only case where we need to provide a base URL to `parseStringToURL`
68+ // because the relative URL is not valid on its own.
69+ const parsedUrl = url . startsWith ( '/' ) ? parseStringToURL ( url , 'thismessage:/' ) : parseStringToURL ( url ) ;
70+ const fullUrl = url . startsWith ( '/' ) ? undefined : parsedUrl ?. href ;
5871
5972 const hasParent = ! ! getActiveSpan ( ) ;
6073
@@ -66,12 +79,13 @@ export function instrumentFetchRequest(
6679 url,
6780 type : 'fetch' ,
6881 'http.method' : method ,
69- 'http.url' : fullUrl ,
70- 'server.address' : parsedUrl ?. host ,
82+ 'http.url' : parsedUrl ?. href ,
7183 [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : spanOrigin ,
7284 [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] : 'http.client' ,
73- ...( parsedUrl ?. search && { 'http.query' : parsedUrl ?. search } ) ,
74- ...( parsedUrl ?. hash && { 'http.fragment' : parsedUrl ?. hash } ) ,
85+ ...( fullUrl && { 'http.url' : fullUrl } ) ,
86+ ...( fullUrl && parsedUrl ?. host && { 'server.address' : parsedUrl . host } ) ,
87+ ...( parsedUrl ?. search && { 'http.query' : parsedUrl . search } ) ,
88+ ...( parsedUrl ?. hash && { 'http.fragment' : parsedUrl . hash } ) ,
7589 } ,
7690 } )
7791 : new SentryNonRecordingSpan ( ) ;
@@ -215,15 +229,6 @@ function _addTracingHeadersToFetchRequest(
215229 }
216230}
217231
218- function getFullURL ( url : string ) : string | undefined {
219- try {
220- const parsed = new URL ( url ) ;
221- return parsed . href ;
222- } catch {
223- return undefined ;
224- }
225- }
226-
227232function endSpan ( span : Span , handlerData : HandlerDataFetch ) : void {
228233 if ( handlerData . response ) {
229234 setHttpStatus ( span , handlerData . response . status ) ;
0 commit comments