@@ -60,6 +60,33 @@ function responseFromReaderText(text: string, releaseLock: () => void): Response
6060 } as Response ;
6161}
6262
63+ function streamingProxyErrorResponse ( params : { chunkCount : number ; chunkSize : number } ) : {
64+ response : Response ;
65+ getReadCount : ( ) => number ;
66+ } {
67+ let reads = 0 ;
68+ const encoder = new TextEncoder ( ) ;
69+ const stream = new ReadableStream < Uint8Array > ( {
70+ pull ( controller ) {
71+ if ( reads >= params . chunkCount ) {
72+ controller . close ( ) ;
73+ return ;
74+ }
75+ reads += 1 ;
76+ controller . enqueue ( encoder . encode ( "a" . repeat ( params . chunkSize ) ) ) ;
77+ } ,
78+ } ) ;
79+
80+ return {
81+ response : new Response ( stream , {
82+ status : 502 ,
83+ statusText : "Bad Gateway" ,
84+ headers : { "Content-Type" : "application/json" } ,
85+ } ) ,
86+ getReadCount : ( ) => reads ,
87+ } ;
88+ }
89+
6390describe ( "streamProxy" , ( ) => {
6491 afterEach ( ( ) => {
6592 vi . unstubAllGlobals ( ) ;
@@ -168,6 +195,30 @@ describe("streamProxy", () => {
168195 expect ( releaseLock ) . toHaveBeenCalledTimes ( 1 ) ;
169196 } ) ;
170197
198+ it ( "stops reading oversized proxy error JSON responses" , async ( ) => {
199+ const streamed = streamingProxyErrorResponse ( { chunkCount : 20 , chunkSize : 1024 * 1024 } ) ;
200+ vi . stubGlobal (
201+ "fetch" ,
202+ vi . fn ( async ( ) => streamed . response ) ,
203+ ) ;
204+
205+ const stream = streamProxy ( model , context , {
206+ authToken : "token" ,
207+ proxyUrl : "https://proxy.example" ,
208+ } ) ;
209+ const events = [ ] ;
210+ for await ( const event of stream ) {
211+ events . push ( event ) ;
212+ }
213+
214+ expect ( events . at ( - 1 ) ?. type ) . toBe ( "error" ) ;
215+ await expect ( stream . result ( ) ) . resolves . toMatchObject ( {
216+ stopReason : "error" ,
217+ errorMessage : "Proxy error: 502 Bad Gateway" ,
218+ } ) ;
219+ expect ( streamed . getReadCount ( ) ) . toBeLessThan ( 20 ) ;
220+ } ) ;
221+
171222 it ( "returns an error result when EOF arrives without a terminal event" , async ( ) => {
172223 vi . stubGlobal (
173224 "fetch" ,
0 commit comments