@@ -85,4 +85,76 @@ describe('buildHeaders', () => {
8585 expect ( inspectNullableHeaders ( buildHeaders ( input ) ) ) . toEqual ( expected ) ;
8686 } ) ;
8787 }
88+
89+ test ( 'normalizes OpenAI headers with locale-invariant ASCII casing' , ( ) => {
90+ expect ( 'OpenAI-Organization' . toLocaleLowerCase ( 'tr-TR' ) ) . toBe ( 'openaı-organization' ) ;
91+ expect ( 'OpenAI-Project' . toLocaleLowerCase ( 'tr-TR' ) ) . toBe ( 'openaı-project' ) ;
92+
93+ const result = buildHeaders ( [
94+ {
95+ 'OpenAI-Organization' : 'org_test' ,
96+ 'OpenAI-Project' : 'proj_test' ,
97+ } ,
98+ ] ) ;
99+
100+ const keys = [ ...result . values . keys ( ) ] ;
101+ expect ( keys ) . toEqual ( [ 'openai-organization' , 'openai-project' ] ) ;
102+ expect ( keys . every ( ( key ) => / ^ [ ! # $ % & ' * + \- . ^ _ ` | ~ 0 - 9 A - Z a - z ] + $ / . test ( key ) ) ) . toBe ( true ) ;
103+ } ) ;
104+
105+ test ( 'rejects header names that lowercase into valid ASCII tokens' , ( ) => {
106+ expect ( 'cooKie' . toLowerCase ( ) ) . toBe ( 'cookie' ) ;
107+ expect ( ( ) => buildHeaders ( [ { cooKie : 'value' } ] ) ) . toThrow (
108+ 'Header name must be a valid HTTP token ["cooKie"]' ,
109+ ) ;
110+ } ) ;
111+
112+ test ( 'passes normalized OpenAI header names to Headers implementations' , ( ) => {
113+ const OriginalHeaders = globalThis . Headers ;
114+
115+ class LocaleSensitiveHeaders {
116+ #values = new Map < string , string > ( ) ;
117+
118+ append ( name : string , value : string ) {
119+ this . #values. set ( normalizeHeaderName ( name ) , value ) ;
120+ }
121+
122+ delete ( name : string ) {
123+ this . #values. delete ( normalizeHeaderName ( name ) ) ;
124+ }
125+
126+ entries ( ) {
127+ return this . #values. entries ( ) ;
128+ }
129+
130+ keys ( ) {
131+ return this . #values. keys ( ) ;
132+ }
133+ }
134+
135+ const normalizeHeaderName = ( name : string ) => {
136+ const normalized = name . toLocaleLowerCase ( 'tr-TR' ) ;
137+ if ( ! / ^ [ ! # $ % & ' * + \- . ^ _ ` | ~ 0 - 9 A - Z a - z ] + $ / . test ( normalized ) ) {
138+ throw new TypeError ( `Header name must be a valid HTTP token ["${ normalized } "]` ) ;
139+ }
140+ return normalized ;
141+ } ;
142+
143+ globalThis . Headers = LocaleSensitiveHeaders as unknown as typeof Headers ;
144+ try {
145+ const result = buildHeaders ( [
146+ {
147+ 'OpenAI-Organization' : 'org_test' ,
148+ 'OpenAI-Project' : 'proj_test' ,
149+ } ,
150+ ] ) ;
151+
152+ expect ( [ ...result . values . entries ( ) ] ) . toEqual ( [
153+ [ 'openai-organization' , 'org_test' ] ,
154+ [ 'openai-project' , 'proj_test' ] ,
155+ ] ) ;
156+ } finally {
157+ globalThis . Headers = OriginalHeaders ;
158+ }
159+ } ) ;
88160} ) ;
0 commit comments