@@ -38,6 +38,32 @@ function createStreamingBinaryResponse(params: {
|
38 | 38 | }; |
39 | 39 | } |
40 | 40 | |
| 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 | + |
41 | 67 | describe("provider error utils", () => { |
42 | 68 | it("formats nested provider error details with request ids", async () => { |
43 | 69 | const response = new Response( |
@@ -211,6 +237,32 @@ describe("provider error utils", () => {
|
211 | 237 | ); |
212 | 238 | }); |
213 | 239 | |
| 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 | + |
214 | 266 | it("caps successful binary responses instead of buffering oversized bodies", async () => { |
215 | 267 | const streamed = createStreamingBinaryResponse({ |
216 | 268 | chunkCount: 20, |
|