diff --git a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts index b9f23e7af..540c68455 100644 --- a/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts +++ b/packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/baggageHeaderUtils.ts @@ -126,7 +126,7 @@ export function formatBaggageHeader(entries: Set): string | null { } const headerValue = formattedParts.join(','); - const byteLength = Buffer.byteLength(headerValue, 'utf8'); + const byteLength = utf8ByteLength(headerValue); if (byteLength > MAX_BYTES) { InternalLog.log( @@ -138,6 +138,40 @@ export function formatBaggageHeader(entries: Set): string | null { return headerValue; } +/** + * Returns the number of bytes needed to encode a string in UTF-8. + * + * Useful as a lightweight alternative to Node.js `Buffer.byteLength()` + * for older environments that do not support it. + * + * @param text - The input string. + * @returns The UTF-8 byte length of the string. + */ +function utf8ByteLength(text: string): number { + let byteLength = text.length; + for (let i = text.length - 1; i >= 0; i--) { + const code = text.charCodeAt(i); + + // 2-byte characters (U+0080 to U+07FF) + if (code > 0x7f && code <= 0x7ff) { + byteLength++; + } + // 3-byte characters (U+0800 to U+FFFF) + else if (code > 0x7ff && code <= 0xffff) { + byteLength += 2; + } + + // Handle surrogate pairs (4-byte characters, e.g. emoji) + // These characters already count as 2 in the initial length + // Encountering the low surrogate already accounts for the full 4 bytes + // (2 from the initial length + 2 for the 3-byte characters logic above) + if (code >= 0xdc00 && code <= 0xdfff) { + i--; // prevents double counting the same character by skipping high surrogate + } + } + return byteLength; +} + /** * Returns a set of valid baggage header characters. */