Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
162 lines
5.1 KiB
Plaintext
162 lines
5.1 KiB
Plaintext
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
|
const core = require('@sentry/core');
|
|
const baggage = require('./baggage.js');
|
|
|
|
const SENTRY_TRACE_HEADER = 'sentry-trace';
|
|
const SENTRY_BAGGAGE_HEADER = 'baggage';
|
|
|
|
// For baggage, we make sure to merge this into a possibly existing header
|
|
const BAGGAGE_HEADER_REGEX = /baggage: (.*)\r\n/;
|
|
|
|
/**
|
|
* Add trace propagation headers to an outgoing fetch/undici request.
|
|
*
|
|
* Checks if the request URL matches trace propagation targets,
|
|
* then injects sentry-trace, traceparent, and baggage headers.
|
|
*/
|
|
// eslint-disable-next-line complexity
|
|
function addTracePropagationHeadersToFetchRequest(
|
|
request,
|
|
propagationDecisionMap,
|
|
) {
|
|
const url = getAbsoluteUrl(request.origin, request.path);
|
|
|
|
// Manually add the trace headers, if it applies
|
|
// Note: We do not use `propagation.inject()` here, because our propagator relies on an active span
|
|
// Which we do not have in this case
|
|
// The propagator _may_ overwrite this, but this should be fine as it is the same data
|
|
const { tracePropagationTargets, propagateTraceparent } = core.getClient()?.getOptions() || {};
|
|
const addedHeaders = core.shouldPropagateTraceForUrl(url, tracePropagationTargets, propagationDecisionMap)
|
|
? core.getTraceData({ propagateTraceparent })
|
|
: undefined;
|
|
|
|
if (!addedHeaders) {
|
|
return;
|
|
}
|
|
|
|
const { 'sentry-trace': sentryTrace, baggage: baggage$1, traceparent } = addedHeaders;
|
|
|
|
// We do not want to overwrite existing headers here
|
|
// If the core UndiciInstrumentation is registered, it will already have set the headers
|
|
// We do not want to add any then
|
|
if (Array.isArray(request.headers)) {
|
|
const requestHeaders = request.headers;
|
|
|
|
// We do not want to overwrite existing header here, if it was already set
|
|
if (sentryTrace && !requestHeaders.includes(SENTRY_TRACE_HEADER)) {
|
|
requestHeaders.push(SENTRY_TRACE_HEADER, sentryTrace);
|
|
}
|
|
|
|
if (traceparent && !requestHeaders.includes('traceparent')) {
|
|
requestHeaders.push('traceparent', traceparent);
|
|
}
|
|
|
|
// For baggage, we make sure to merge this into a possibly existing header
|
|
const existingBaggagePos = requestHeaders.findIndex(header => header === SENTRY_BAGGAGE_HEADER);
|
|
if (baggage$1 && existingBaggagePos === -1) {
|
|
requestHeaders.push(SENTRY_BAGGAGE_HEADER, baggage$1);
|
|
} else if (baggage$1) {
|
|
const existingBaggage = requestHeaders[existingBaggagePos + 1];
|
|
const merged = baggage.mergeBaggageHeaders(existingBaggage, baggage$1);
|
|
if (merged) {
|
|
requestHeaders[existingBaggagePos + 1] = merged;
|
|
}
|
|
}
|
|
} else {
|
|
const requestHeaders = request.headers;
|
|
// We do not want to overwrite existing header here, if it was already set
|
|
if (sentryTrace && !requestHeaders.includes(`${SENTRY_TRACE_HEADER}:`)) {
|
|
request.headers += `${SENTRY_TRACE_HEADER}: ${sentryTrace}\r\n`;
|
|
}
|
|
|
|
if (traceparent && !requestHeaders.includes('traceparent:')) {
|
|
request.headers += `traceparent: ${traceparent}\r\n`;
|
|
}
|
|
|
|
const existingBaggage = request.headers.match(BAGGAGE_HEADER_REGEX)?.[1];
|
|
if (baggage$1 && !existingBaggage) {
|
|
request.headers += `${SENTRY_BAGGAGE_HEADER}: ${baggage$1}\r\n`;
|
|
} else if (baggage$1) {
|
|
const merged = baggage.mergeBaggageHeaders(existingBaggage, baggage$1);
|
|
if (merged) {
|
|
request.headers = request.headers.replace(BAGGAGE_HEADER_REGEX, `baggage: ${merged}\r\n`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Add a breadcrumb for an outgoing fetch/undici request. */
|
|
function addFetchRequestBreadcrumb(request, response) {
|
|
const data = getBreadcrumbData(request);
|
|
|
|
const statusCode = response.statusCode;
|
|
const level = core.getBreadcrumbLogLevelFromHttpStatusCode(statusCode);
|
|
|
|
core.addBreadcrumb(
|
|
{
|
|
category: 'http',
|
|
data: {
|
|
status_code: statusCode,
|
|
...data,
|
|
},
|
|
type: 'http',
|
|
level,
|
|
},
|
|
{
|
|
event: 'response',
|
|
request,
|
|
response,
|
|
},
|
|
);
|
|
}
|
|
|
|
function getBreadcrumbData(request) {
|
|
try {
|
|
const url = getAbsoluteUrl(request.origin, request.path);
|
|
const parsedUrl = core.parseUrl(url);
|
|
|
|
const data = {
|
|
url: core.getSanitizedUrlString(parsedUrl),
|
|
'http.method': request.method || 'GET',
|
|
};
|
|
|
|
if (parsedUrl.search) {
|
|
data['http.query'] = parsedUrl.search;
|
|
}
|
|
if (parsedUrl.hash) {
|
|
data['http.fragment'] = parsedUrl.hash;
|
|
}
|
|
|
|
return data;
|
|
} catch {
|
|
return {};
|
|
}
|
|
}
|
|
|
|
/** Get the absolute URL from an origin and path. */
|
|
function getAbsoluteUrl(origin, path = '/') {
|
|
try {
|
|
const url = new URL(path, origin);
|
|
return url.toString();
|
|
} catch {
|
|
// fallback: Construct it on our own
|
|
const url = `${origin}`;
|
|
|
|
if (url.endsWith('/') && path.startsWith('/')) {
|
|
return `${url}${path.slice(1)}`;
|
|
}
|
|
|
|
if (!url.endsWith('/') && !path.startsWith('/')) {
|
|
return `${url}/${path}`;
|
|
}
|
|
|
|
return `${url}${path}`;
|
|
}
|
|
}
|
|
|
|
exports.addFetchRequestBreadcrumb = addFetchRequestBreadcrumb;
|
|
exports.addTracePropagationHeadersToFetchRequest = addTracePropagationHeadersToFetchRequest;
|
|
exports.getAbsoluteUrl = getAbsoluteUrl;
|
|
//# sourceMappingURL=outgoingFetchRequest.js.map
|