@@ -38,6 +38,32 @@ function createStreamingBinaryResponse(params: {
3838 } ;
3939}
4040
41+ function createStreamingJsonResponse ( params : { chunkCount : number ; chunkSize : number } ) : {
42+ response : Response ;
43+ getReadCount : ( ) => number ;
44+ } {
45+ // Streaming fixture proves oversized JSON reads stop before buffering everything.
46+ let reads = 0 ;
47+ const encoder = new TextEncoder ( ) ;
48+ const stream = new ReadableStream < Uint8Array > ( {
49+ pull ( controller ) {
50+ if ( reads >= params . chunkCount ) {
51+ controller . close ( ) ;
52+ return ;
53+ }
54+ reads += 1 ;
55+ controller . enqueue ( encoder . encode ( "a" . repeat ( params . chunkSize ) ) ) ;
56+ } ,
57+ } ) ;
58+ return {
59+ response : new Response ( stream , {
60+ status : 200 ,
61+ headers : { "Content-Type" : "application/json" } ,
62+ } ) ,
63+ getReadCount : ( ) => reads ,
64+ } ;
65+ }
66+
4167describe ( "provider error utils" , ( ) => {
4268 it ( "formats nested provider error details with request ids" , async ( ) => {
4369 const response = new Response (
@@ -211,6 +237,32 @@ describe("provider error utils", () => {
211237 ) ;
212238 } ) ;
213239
240+ it ( "parses well-formed JSON responses under the byte cap" , async ( ) => {
241+ const response = new Response ( JSON . stringify ( { models : [ "a" , "b" ] } ) , {
242+ status : 200 ,
243+ headers : { "content-type" : "application/json" } ,
244+ } ) ;
245+
246+ await expect (
247+ readProviderJsonResponse < { models : string [ ] } > ( response , "Provider catalog failed" ) ,
248+ ) . resolves . toEqual ( { models : [ "a" , "b" ] } ) ;
249+ } ) ;
250+
251+ it ( "caps successful JSON responses instead of buffering oversized bodies" , async ( ) => {
252+ const streamed = createStreamingJsonResponse ( {
253+ chunkCount : 20 ,
254+ chunkSize : 1024 ,
255+ } ) ;
256+
257+ await expect (
258+ readProviderJsonResponse ( streamed . response , "Provider catalog failed" , {
259+ maxBytes : 2048 ,
260+ } ) ,
261+ ) . rejects . toThrow ( "Provider catalog failed: JSON response exceeds 2048 bytes" ) ;
262+
263+ expect ( streamed . getReadCount ( ) ) . toBeLessThan ( 20 ) ;
264+ } ) ;
265+
214266 it ( "caps successful binary responses instead of buffering oversized bodies" , async ( ) => {
215267 const streamed = createStreamingBinaryResponse ( {
216268 chunkCount : 20 ,
0 commit comments