@@ -73,7 +73,8 @@ function needsBase64Encoding(value: string): boolean {
7373 */
7474function 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
100136abstract 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