@@ -1609,3 +1609,77 @@ test('openai-bridge maps reasoning effort when converting to upstream chat compl
16091609 await upstream . close ( ) ;
16101610 await rm ( tmpDir , { recursive : true , force : true } ) ;
16111611} ) ;
1612+
1613+ test ( 'openai-bridge does not write 500 headers after response headers were already sent' , async ( ) => {
1614+ const upstream = http . createServer ( ( req , res ) => {
1615+ if ( req . url === '/v1/chat/completions' && req . method === 'POST' ) {
1616+ res . writeHead ( 200 , { 'Content-Type' : 'application/json' } ) ;
1617+ res . end ( JSON . stringify ( {
1618+ id : 'chatcmpl_headers_sent_regression' ,
1619+ model : 'gpt-test' ,
1620+ choices : [ { message : { role : 'assistant' , content : 'ok' } } ]
1621+ } ) ) ;
1622+ return ;
1623+ }
1624+ res . writeHead ( 404 , { 'Content-Type' : 'application/json' } ) ;
1625+ res . end ( JSON . stringify ( { error : 'not found' } ) ) ;
1626+ } ) ;
1627+ const { port : upstreamPort } = await listen ( upstream ) ;
1628+
1629+ const tmpDir = await mkdtemp ( path . join ( os . tmpdir ( ) , 'codexmate-bridge-test-' ) ) ;
1630+ const settingsFile = path . join ( tmpDir , 'bridge.json' ) ;
1631+ await writeFile ( settingsFile , JSON . stringify ( {
1632+ version : 1 ,
1633+ providers : {
1634+ test : { baseUrl : `http://127.0.0.1:${ upstreamPort } /v1` , apiKey : 'sk-upstream' }
1635+ }
1636+ } ) , 'utf-8' ) ;
1637+
1638+ let uncaught = null ;
1639+ const onUncaught = ( err ) => { uncaught = err ; } ;
1640+ process . once ( 'uncaughtException' , onUncaught ) ;
1641+
1642+ const handler = createOpenaiBridgeHttpHandler ( { settingsFile, expectedToken : 'codexmate' } ) ;
1643+ const bridge = http . createServer ( ( req , res ) => {
1644+ const originalWriteHead = res . writeHead . bind ( res ) ;
1645+ let wroteSuccessHeader = false ;
1646+ res . writeHead = function patchedWriteHead ( statusCode , headers ) {
1647+ if ( statusCode === 200 ) wroteSuccessHeader = true ;
1648+ if ( wroteSuccessHeader && statusCode === 500 ) {
1649+ throw new Error ( 'regression: attempted second writeHead after headers sent' ) ;
1650+ }
1651+ return originalWriteHead ( statusCode , headers ) ;
1652+ } ;
1653+ const originalEnd = res . end . bind ( res ) ;
1654+ res . end = function patchedEnd ( chunk , encoding , cb ) {
1655+ if ( wroteSuccessHeader && ! res . writableEnded ) {
1656+ originalEnd ( chunk , encoding , cb ) ;
1657+ throw new Error ( 'simulated post-header write failure' ) ;
1658+ }
1659+ return originalEnd ( chunk , encoding , cb ) ;
1660+ } ;
1661+ if ( ! handler ( req , res ) ) {
1662+ res . statusCode = 404 ;
1663+ res . end ( 'not handled' ) ;
1664+ }
1665+ } ) ;
1666+ const { port : bridgePort } = await listen ( bridge ) ;
1667+
1668+ const resp = await requestText ( `http://127.0.0.1:${ bridgePort } /bridge/openai/test/v1/responses` , {
1669+ method : 'POST' ,
1670+ headers : {
1671+ 'Content-Type' : 'application/json' ,
1672+ 'Accept' : 'application/json' ,
1673+ 'Authorization' : 'Bearer codexmate'
1674+ } ,
1675+ body : { model : 'gpt-test' , input : 'ping' }
1676+ } ) ;
1677+
1678+ assert . equal ( resp . status , 200 ) ;
1679+ assert . equal ( uncaught , null ) ;
1680+
1681+ process . removeListener ( 'uncaughtException' , onUncaught ) ;
1682+ await bridge . close ( ) ;
1683+ await upstream . close ( ) ;
1684+ await rm ( tmpDir , { recursive : true , force : true } ) ;
1685+ } ) ;
0 commit comments