diff --git a/packages/core/src/utils-hoist/baggage.ts b/packages/core/src/utils-hoist/baggage.ts index 9b97f0a92eea..e3204d8b2105 100644 --- a/packages/core/src/utils-hoist/baggage.ts +++ b/packages/core/src/utils-hoist/baggage.ts @@ -113,7 +113,17 @@ export function parseBaggageHeader( function baggageHeaderToObject(baggageHeader: string): Record { return baggageHeader .split(',') - .map(baggageEntry => baggageEntry.split('=').map(keyOrValue => decodeURIComponent(keyOrValue.trim()))) + .map(baggageEntry => + baggageEntry.split('=').map(keyOrValue => { + try { + return decodeURIComponent(keyOrValue.trim()); + } catch { + // We ignore errors here, e.g. if the value cannot be URL decoded. + // This will then be skipped in the next step + return; + } + }), + ) .reduce>((acc, [key, value]) => { if (key && value) { acc[key] = value; diff --git a/packages/core/test/utils-hoist/baggage.test.ts b/packages/core/test/utils-hoist/baggage.test.ts index d24b11c9f62e..c05ac0d5dd96 100644 --- a/packages/core/test/utils-hoist/baggage.test.ts +++ b/packages/core/test/utils-hoist/baggage.test.ts @@ -1,7 +1,8 @@ -import { expect, test } from 'vitest'; +import { describe, expect, test } from 'vitest'; import { baggageHeaderToDynamicSamplingContext, dynamicSamplingContextToSentryBaggageHeader, + parseBaggageHeader, } from '../../src/utils-hoist/baggage'; test.each([ @@ -27,7 +28,7 @@ test.each([ { environment: 'production', release: '1.0.1' }, ], [42, undefined], -])('baggageHeaderToDynamicSamplingContext(%p) should return %p', (input, expectedOutput) => { +])('baggageHeaderToDynamicSamplingContext(%j) should return %j', (input, expectedOutput) => { expect(baggageHeaderToDynamicSamplingContext(input)).toStrictEqual(expectedOutput); }); @@ -40,6 +41,34 @@ test.each([ { release: 'abcdf', environment: '1234', someRandomKey: 'foo' }, 'sentry-release=abcdf,sentry-environment=1234,sentry-someRandomKey=foo', ], -])('dynamicSamplingContextToSentryBaggageHeader(%p) should return %p', (input, expectedOutput) => { +])('dynamicSamplingContextToSentryBaggageHeader(%j) should return %j', (input, expectedOutput) => { expect(dynamicSamplingContextToSentryBaggageHeader(input)).toStrictEqual(expectedOutput); }); + +describe('parseBaggageHeader', () => { + test.each([ + [undefined, undefined], + [1, undefined], + [true, undefined], + [false, undefined], + [null, undefined], + [NaN, undefined], + [Infinity, undefined], + [0, undefined], + ['', undefined], + ['foo', {}], + [ + 'sentry-environment=production,sentry-release=10.0.2,foo=bar', + { 'sentry-environment': 'production', 'sentry-release': '10.0.2', foo: 'bar' }, + ], + [ + ['sentry-environment=production,sentry-release=10.0.2,foo=bar', 'foo2=bar2'], + { 'sentry-environment': 'production', 'sentry-release': '10.0.2', foo: 'bar', foo2: 'bar2' }, + ], + // ignores malformed baggage entries + ['foo=bar,foo2=%3G', { foo: 'bar' }], + ])('parseBaggageHeader(%j) should return %j', (input, expectedOutput) => { + const actual = parseBaggageHeader(input); + expect(actual).toStrictEqual(expectedOutput); + }); +});