Skip to content

Commit fe6859b

Browse files
author
Tarek Mahmoud Sayed
committed
Use numeric comparison for number header values
Compare number header values numerically instead of as strings to accommodate cross-SDK floating point representation differences (e.g., '42' vs '42.0'). For integers, exact numeric match is required. For decimals, a tolerance of 1e-9 is allowed. See SEP-2243 discussion on number precision.
1 parent fc64850 commit fe6859b

1 file changed

Lines changed: 42 additions & 2 deletions

File tree

src/scenarios/client/http-custom-headers.ts

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ function needsBase64Encoding(value: string): boolean {
7373
*/
7474
function validateEncodedHeader(
7575
rawHeader: string,
76-
bodyValue: string
76+
bodyValue: string,
77+
valueType?: string
7778
): string | null {
7879
if (needsBase64Encoding(bodyValue)) {
7980
// Value requires Base64 encoding
@@ -83,19 +84,54 @@ function validateEncodedHeader(
8384
return `Value '${bodyValue}' requires Base64 encoding but header was sent as plain: '${rawHeader}'`;
8485
}
8586
const decoded = Buffer.from(base64Match[1], 'base64').toString('utf-8');
87+
if (valueType === 'number') {
88+
return compareNumericValues(decoded, bodyValue);
89+
}
8690
if (decoded !== bodyValue) {
8791
return `Base64-decoded header value '${decoded}' does not match body value '${bodyValue}'`;
8892
}
8993
return null;
9094
}
9195
// Plain ASCII - compare directly (after decoding if Base64 was used)
9296
const decoded = decodeHeaderValue(rawHeader);
97+
if (valueType === 'number') {
98+
return compareNumericValues(decoded, bodyValue);
99+
}
93100
if (decoded !== bodyValue) {
94101
return `Header value '${decoded}' (raw: '${rawHeader}') does not match body value '${bodyValue}'`;
95102
}
96103
return null;
97104
}
98105

106+
/**
107+
* Compare two string representations of numbers numerically.
108+
* For integers, requires exact match. For decimals, allows
109+
* a tolerance of 1e-9 to account for cross-SDK floating point
110+
* representation differences.
111+
*/
112+
function compareNumericValues(
113+
headerValue: string,
114+
bodyValue: string
115+
): string | null {
116+
const headerNum = Number(headerValue);
117+
const bodyNum = Number(bodyValue);
118+
if (isNaN(headerNum) || isNaN(bodyNum)) {
119+
return `Non-numeric value in number comparison: header='${headerValue}', body='${bodyValue}'`;
120+
}
121+
if (Number.isInteger(bodyNum)) {
122+
// Integer: require exact numeric match (e.g. 42 === 42.0)
123+
if (headerNum !== bodyNum) {
124+
return `Numeric header value ${headerNum} does not match body value ${bodyNum}`;
125+
}
126+
} else {
127+
// Decimal: allow tolerance of 1e-9
128+
if (Math.abs(headerNum - bodyNum) > 1e-9) {
129+
return `Numeric header value ${headerNum} does not match body value ${bodyNum} (difference ${Math.abs(headerNum - bodyNum)} exceeds tolerance 1e-9)`;
130+
}
131+
}
132+
return null;
133+
}
134+
99135
// Shared server boilerplate for Scenario implementations
100136
abstract class BaseHttpScenario implements Scenario {
101137
abstract name: string;
@@ -684,9 +720,13 @@ export class HttpCustomHeadersScenario extends BaseHttpScenario {
684720
expectedString = String(bodyValue);
685721
}
686722

723+
// For numbers, compare numerically to allow for cross-SDK
724+
// floating point representation differences (e.g., "42" vs "42.0").
725+
// See SEP-2243 discussion on number precision.
687726
const validationError = validateEncodedHeader(
688727
rawHeaderValue,
689-
expectedString
728+
expectedString,
729+
valueType
690730
);
691731
if (validationError) {
692732
errors.push(validationError);

0 commit comments

Comments
 (0)