Skip to content

Commit

Permalink
fix(ClientRequest): prevent req.write() callbacks from being called…
Browse files Browse the repository at this point in the history
… twice on passthrough (#685)
  • Loading branch information
kettanaito authored Dec 1, 2024
1 parent 0ce43e8 commit e3c2a0b
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 8 deletions.
18 changes: 11 additions & 7 deletions src/interceptors/ClientRequest/MockHttpSocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -420,13 +420,17 @@ export class MockHttpSocket extends MockSocket {
}

private flushWriteBuffer(): void {
for (const [, , callback] of this.writeBuffer) {
/**
* @note If the write callbacks are ever called twice,
* we need to mark them with a symbol so they aren't called
* again in the `passthrough` method.
*/
callback?.()
for (const writeCall of this.writeBuffer) {
if (typeof writeCall[2] === 'function') {
writeCall[2]()
/**
* @note Remove the callback from the write call
* so it doesn't get called twice on passthrough
* if `request.end()` was called within `request.write()`.
* @see https://github.com/mswjs/interceptors/issues/684
*/
writeCall[2] = undefined
}
}
}

Expand Down
21 changes: 20 additions & 1 deletion test/modules/http/compliance/http-req-write.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ it('calls all write callbacks before the mocked response', async () => {
expect(await text()).toBe('hello world')
})

it('does not call write callbacks ...', async () => {
it('calls the write callbacks when reading request body in the interceptor', async () => {
const requestBodyCallback = vi.fn()
const requestWriteCallback = vi.fn()

Expand All @@ -220,3 +220,22 @@ it('does not call write callbacks ...', async () => {
// Must send the correct request body to the server.
expect(await text()).toBe('onetwothree')
})

/**
* @see https://github.com/mswjs/interceptors/issues/684
*/
it('calls the write callback once for a request that ends inside a write', async () => {
const requestWriteCallback = vi.fn()

const request = http.request(httpServer.http.url('/resource'), {
method: 'POST',
headers: { 'content-type': 'text/plain' },
})
request.write('one', 'utf8', () => {
requestWriteCallback()
request.end()
})

await waitForClientRequest(request)
expect(requestWriteCallback).toHaveBeenCalledTimes(1)
})

0 comments on commit e3c2a0b

Please sign in to comment.