Skip to content

Commit f78fe50

Browse files
committed
feat(baggage): Added double baggage prevention logic and introduce
1 parent 83445eb commit f78fe50

3 files changed

Lines changed: 127 additions & 1 deletion

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import * as Sentry from '@sentry/node';
2+
import { loggingTransport } from '@sentry-internal/node-integration-tests';
3+
4+
Sentry.init({
5+
dsn: 'https://public@dsn.ingest.sentry.io/1337',
6+
release: '1.0',
7+
tracesSampleRate: 1.0,
8+
tracePropagationTargets: [/localhost/],
9+
transport: loggingTransport,
10+
});
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import http from 'http';
2+
import * as Sentry from '@sentry/node';
3+
4+
let capturedHeaders = {};
5+
const targetServer = http.createServer((req, res) => {
6+
capturedHeaders = {
7+
'sentry-trace': req.headers['sentry-trace'],
8+
baggage: req.headers['baggage'],
9+
};
10+
res.writeHead(200);
11+
res.end('ok');
12+
});
13+
14+
targetServer.listen(0, async () => {
15+
const targetPort = targetServer.address().port;
16+
const targetUrl = `http://localhost:${targetPort}/target`;
17+
18+
try {
19+
// Step 1: fetch with manual getTraceData() headers
20+
console.log('[TEST 1] Fetch with manual getTraceData() headers');
21+
capturedHeaders = {};
22+
await fetch(targetUrl, { headers: { ...Sentry.getTraceData() } });
23+
const fetchHeaders1 = { ...capturedHeaders };
24+
25+
// Step 2: fetch without manual headers
26+
console.log('[TEST 2] Fetch without manual headers');
27+
capturedHeaders = {};
28+
await fetch(targetUrl);
29+
const fetchHeaders2 = { ...capturedHeaders };
30+
31+
// Step 3: http.request with manual getTraceData() headers
32+
console.log('[TEST 3] HTTP request with manual getTraceData() headers');
33+
capturedHeaders = {};
34+
await new Promise((resolve, reject) => {
35+
const traceData = Sentry.getTraceData();
36+
const req = http.request(
37+
{
38+
hostname: 'localhost',
39+
port: targetPort,
40+
path: '/target',
41+
method: 'GET',
42+
headers: traceData,
43+
},
44+
res => {
45+
res.on('data', () => {});
46+
res.on('end', () => resolve());
47+
},
48+
);
49+
req.on('error', reject);
50+
req.end();
51+
});
52+
const httpHeaders = { ...capturedHeaders };
53+
54+
// Step 4: fetch with custom + manual sentry baggage
55+
console.log('[TEST 4] Fetch with custom baggage + manual sentry baggage');
56+
capturedHeaders = {};
57+
const traceData = Sentry.getTraceData();
58+
await fetch(targetUrl, {
59+
headers: {
60+
...traceData,
61+
baggage: `custom-key=value,${traceData.baggage}`,
62+
},
63+
});
64+
const fetchHeaders4 = { ...capturedHeaders };
65+
66+
const results = {
67+
test1: {
68+
sentryTrace: fetchHeaders1['sentry-trace'],
69+
baggage: fetchHeaders1.baggage,
70+
hasDuplicateSentryTrace: fetchHeaders1['sentry-trace']?.includes(','),
71+
sentryBaggageCount: (fetchHeaders1.baggage?.match(/sentry-/g) || []).length,
72+
},
73+
test2: {
74+
sentryTrace: fetchHeaders2['sentry-trace'],
75+
baggage: fetchHeaders2.baggage,
76+
hasDuplicateSentryTrace: fetchHeaders2['sentry-trace']?.includes(','),
77+
sentryBaggageCount: (fetchHeaders2.baggage?.match(/sentry-/g) || []).length,
78+
},
79+
test3: {
80+
sentryTrace: httpHeaders['sentry-trace'],
81+
baggage: httpHeaders.baggage,
82+
hasDuplicateSentryTrace: httpHeaders['sentry-trace']?.includes(','),
83+
sentryBaggageCount: (httpHeaders.baggage?.match(/sentry-/g) || []).length,
84+
},
85+
test4: {
86+
sentryTrace: fetchHeaders4['sentry-trace'],
87+
baggage: fetchHeaders4.baggage,
88+
hasDuplicateSentryTrace: fetchHeaders4['sentry-trace']?.includes(','),
89+
hasCustomBaggage: fetchHeaders4.baggage?.includes('custom-key=value'),
90+
sentryBaggageCount: (fetchHeaders4.baggage?.match(/sentry-/g) || []).length,
91+
},
92+
};
93+
94+
console.log('RESULTS:', JSON.stringify(results));
95+
} catch (error) {
96+
console.error('Test error:', error);
97+
} finally {
98+
targetServer.close();
99+
}
100+
});

packages/node-core/src/utils/baggage.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,20 @@
1-
import { objectToBaggageHeader, parseBaggageHeader } from '@sentry/core';
1+
import { objectToBaggageHeader, parseBaggageHeader, SENTRY_BAGGAGE_KEY_PREFIX } from '@sentry/core';
2+
3+
/**
4+
* To check if a baggage header contains any Sentry baggage values.
5+
*
6+
* @param baggageHeader The baggage header to check
7+
* @returns true if the baggage header contains any keys with the 'sentry-' prefix
8+
*/
9+
export function hasSentryBaggageValues(baggageHeader: string | string[] | undefined): boolean {
10+
if (!baggageHeader) {
11+
return false;
12+
}
13+
14+
const baggageString = Array.isArray(baggageHeader) ? baggageHeader.join(',') : baggageHeader;
15+
16+
return baggageString.split(',').some(entry => entry.trim().startsWith(SENTRY_BAGGAGE_KEY_PREFIX));
17+
}
218

319
/**
420
* Merge two baggage headers into one, where the existing one takes precedence.

0 commit comments

Comments
 (0)