Skip to content

Commit fa0f0ff

Browse files
committed
fix: preserve passthrough socket close ordering
1 parent c3f08d4 commit fa0f0ff

1 file changed

Lines changed: 26 additions & 2 deletions

File tree

src/interceptors/ClientRequest/MockHttpSocket.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,17 @@ export class MockHttpSocket extends MockSocket {
286286
})
287287
}
288288

289+
let passthroughReadableEnded = false
290+
let passthroughCloseEmitted = false
291+
const emitPassthroughCloseOnce = (hadError: boolean) => {
292+
if (passthroughCloseEmitted) {
293+
return
294+
}
295+
296+
passthroughCloseEmitted = true
297+
this.emit('close', hadError)
298+
}
299+
289300
socket
290301
.on('lookup', (...args) => this.emit('lookup', ...args))
291302
.on('connect', () => {
@@ -311,8 +322,21 @@ export class MockHttpSocket extends MockSocket {
311322
.on('timeout', () => this.emit('timeout'))
312323
.on('prefinish', () => this.emit('prefinish'))
313324
.on('finish', () => this.emit('finish'))
314-
.on('close', (hadError) => this.emit('close', hadError))
315-
.on('end', () => this.emit('end'))
325+
.on('close', (hadError) => {
326+
if (hadError || !passthroughReadableEnded || this.readableEnded) {
327+
emitPassthroughCloseOnce(hadError)
328+
return
329+
}
330+
331+
// Node's HTTP client expects the response readable side to end before
332+
// the socket closes. The original socket can close before the pushed
333+
// EOF surfaces on this socket, so defer "close" to avoid an abort.
334+
this.once('end', () => emitPassthroughCloseOnce(hadError))
335+
})
336+
.on('end', () => {
337+
passthroughReadableEnded = true
338+
this.push(null)
339+
})
316340
}
317341

318342
/**

0 commit comments

Comments
 (0)