@@ -2,7 +2,6 @@ import { createServer, type Server } from "node:http";
22import { describe , expect , it , vi } from "vitest" ;
33import { createClickClackClient } from "./http-client.js" ;
44
5- const CLICKCLACK_JSON_CAP_BYTES = 16 * 1024 * 1024 ;
65const LOOPBACK_RESPONSE_BYTES = 18 * 1024 * 1024 ;
76
87async function listenLoopbackServer ( server : Server ) : Promise < number > {
@@ -25,23 +24,54 @@ function createOversizedJsonServer(): { server: Server; closed: Promise<number>
2524 const closed = new Promise < number > ( ( resolve ) => {
2625 resolveClosed = resolve ;
2726 } ) ;
28- const server = createServer ( ( _req , res ) => {
27+ const server = createServer ( ( req , res ) => {
2928 let sentBytes = 0 ;
30- const chunk = Buffer . alloc ( 64 * 1024 , 0x20 ) ;
31- res . writeHead ( 200 , { "content-type" : "application/json" } ) ;
32- const timer = setInterval ( ( ) => {
33- if ( sentBytes >= LOOPBACK_RESPONSE_BYTES ) {
34- clearInterval ( timer ) ;
35- res . end ( ) ;
36- return ;
29+ let stopped = false ;
30+ let prefixSent = false ;
31+ const prefixChunk = Buffer . from ( '{"user":{"id":"' ) ;
32+ const bodyChunk = Buffer . alloc ( 64 * 1024 , 0x61 ) ;
33+ const suffixChunk = Buffer . from ( '"}}' ) ;
34+ const writeBuffer = ( buffer : Buffer ) => {
35+ sentBytes += buffer . length ;
36+ if ( ! res . write ( buffer ) ) {
37+ res . once ( "drain" , writeChunks ) ;
38+ return false ;
39+ }
40+ return true ;
41+ } ;
42+ const writeChunks = ( ) => {
43+ if ( ! prefixSent ) {
44+ prefixSent = true ;
45+ if ( ! writeBuffer ( prefixChunk ) ) {
46+ return ;
47+ }
48+ }
49+ while ( true ) {
50+ if ( stopped ) {
51+ return ;
52+ }
53+ if ( sentBytes + bodyChunk . length + suffixChunk . length >= LOOPBACK_RESPONSE_BYTES ) {
54+ break ;
55+ }
56+ if ( ! writeBuffer ( bodyChunk ) ) {
57+ return ;
58+ }
3759 }
38- sentBytes += chunk . length ;
39- res . write ( chunk ) ;
40- } , 1 ) ;
60+ if ( ! stopped ) {
61+ sentBytes += suffixChunk . length ;
62+ res . end ( suffixChunk ) ;
63+ }
64+ } ;
65+ res . writeHead ( 200 , { connection : "close" , "content-type" : "application/json" } ) ;
4166 res . on ( "close" , ( ) => {
42- clearInterval ( timer ) ;
67+ stopped = true ;
4368 resolveClosed ( sentBytes ) ;
4469 } ) ;
70+ req . on ( "aborted" , ( ) => {
71+ stopped = true ;
72+ res . destroy ( ) ;
73+ } ) ;
74+ writeChunks ( ) ;
4575 } ) ;
4676 return { server, closed } ;
4777}
@@ -96,8 +126,8 @@ describe("ClickClack HTTP client", () => {
96126 await expect ( client . me ( ) ) . rejects . toThrow (
97127 "ClickClack response: JSON response exceeds 16777216 bytes" ,
98128 ) ;
99- await expect ( closed ) . resolves . toBeLessThan ( LOOPBACK_RESPONSE_BYTES ) ;
100- await expect ( closed ) . resolves . toBeGreaterThan ( CLICKCLACK_JSON_CAP_BYTES ) ;
129+ const sentBytes = await closed ;
130+ expect ( sentBytes ) . toBeLessThan ( LOOPBACK_RESPONSE_BYTES ) ;
101131 } finally {
102132 server . close ( ) ;
103133 }
0 commit comments