From 103f8c3e3ac992dfcbf9e0132f90db4a6ef73a2a Mon Sep 17 00:00:00 2001 From: Michael Solomon Date: Sat, 30 Sep 2023 17:19:45 +0300 Subject: [PATCH 1/4] failing test --- .../ClientRequest/NodeClientRequest.test.ts | 23 +++++++++++++++++++ .../ClientRequest/NodeClientRequest.ts | 5 ++++ 2 files changed, 28 insertions(+) diff --git a/src/interceptors/ClientRequest/NodeClientRequest.test.ts b/src/interceptors/ClientRequest/NodeClientRequest.test.ts index 57459117..ee628948 100644 --- a/src/interceptors/ClientRequest/NodeClientRequest.test.ts +++ b/src/interceptors/ClientRequest/NodeClientRequest.test.ts @@ -315,3 +315,26 @@ it('does not send request body to the original server given mocked response', as const text = await getIncomingMessageBody(response) expect(text).toBe('mock created!') }) + +it.only('emits the ERR_STREAM_WRITE_AFTER_END error when write after end given no mocked response', async () => { + const emitter = new Emitter() + const request = new NodeClientRequest( + normalizeClientRequestArgs('http:', httpServer.http.url('/write')), + { + emitter, + logger, + } + ) + + const errorReceived = new DeferredPromise() + request.on('error', (error) => { + errorReceived.resolve(error) + }) + + request.end() + request.write('foo') + + const error = await errorReceived + + expect(error.code).toBe('ERR_STREAM_WRITE_AFTER_END') +}) \ No newline at end of file diff --git a/src/interceptors/ClientRequest/NodeClientRequest.ts b/src/interceptors/ClientRequest/NodeClientRequest.ts index b4df0943..d6d03846 100644 --- a/src/interceptors/ClientRequest/NodeClientRequest.ts +++ b/src/interceptors/ClientRequest/NodeClientRequest.ts @@ -99,6 +99,11 @@ export class NodeClientRequest extends ClientRequest { } write(...args: ClientRequestWriteArgs): boolean { + // Fallback to native behavior to throw + if (this.destroyed || this.finished) { + return super.write(args) + } + const [chunk, encoding, callback] = normalizeClientRequestWriteArgs(args) this.logger.info('write:', { chunk, encoding, callback }) this.chunks.push({ chunk, encoding }) From 8204bd9137eed2d564cb9bd7fbb155284c15393a Mon Sep 17 00:00:00 2001 From: Michael Solomon Date: Tue, 3 Oct 2023 22:52:48 +0300 Subject: [PATCH 2/4] fix tests --- .../ClientRequest/NodeClientRequest.test.ts | 23 ---------- .../compliance/http-req-end-and-write.test.ts | 42 +++++++++++++++++++ 2 files changed, 42 insertions(+), 23 deletions(-) create mode 100644 test/modules/http/compliance/http-req-end-and-write.test.ts diff --git a/src/interceptors/ClientRequest/NodeClientRequest.test.ts b/src/interceptors/ClientRequest/NodeClientRequest.test.ts index ee628948..6db20556 100644 --- a/src/interceptors/ClientRequest/NodeClientRequest.test.ts +++ b/src/interceptors/ClientRequest/NodeClientRequest.test.ts @@ -314,27 +314,4 @@ it('does not send request body to the original server given mocked response', as const text = await getIncomingMessageBody(response) expect(text).toBe('mock created!') -}) - -it.only('emits the ERR_STREAM_WRITE_AFTER_END error when write after end given no mocked response', async () => { - const emitter = new Emitter() - const request = new NodeClientRequest( - normalizeClientRequestArgs('http:', httpServer.http.url('/write')), - { - emitter, - logger, - } - ) - - const errorReceived = new DeferredPromise() - request.on('error', (error) => { - errorReceived.resolve(error) - }) - - request.end() - request.write('foo') - - const error = await errorReceived - - expect(error.code).toBe('ERR_STREAM_WRITE_AFTER_END') }) \ No newline at end of file diff --git a/test/modules/http/compliance/http-req-end-and-write.test.ts b/test/modules/http/compliance/http-req-end-and-write.test.ts new file mode 100644 index 00000000..9192e31c --- /dev/null +++ b/test/modules/http/compliance/http-req-end-and-write.test.ts @@ -0,0 +1,42 @@ +import { it, expect, beforeAll, afterAll } from 'vitest' +import http from 'http' +import express from 'express' +import { HttpServer } from '@open-draft/test-server/http' +import { DeferredPromise } from '@open-draft/deferred-promise' +import { ClientRequestInterceptor } from '../../../../src/interceptors/ClientRequest' + +const httpServer = new HttpServer((app) => { + app.post('/resource', express.text({ type: '*/*' }), (req, res) => { + res.send(req.body) + }) +}) + +const interceptor = new ClientRequestInterceptor() + +beforeAll(async () => { + interceptor.apply() + await httpServer.listen() +}) + +afterAll(async () => { + interceptor.dispose() + await httpServer.close() +}) + +it('emits the ERR_STREAM_WRITE_AFTER_END error when write after end given no mocked response', async () => { + const req = http.request(httpServer.http.url('/resource')) + + const errorReceived = new DeferredPromise() + req.on('error', (error) => { + console.log(error); + + errorReceived.resolve(error) + }) + + req.end() + req.write('foo') + + const error = await errorReceived + + expect(error.code).toBe('ERR_STREAM_WRITE_AFTER_END') +}) \ No newline at end of file From 896f6c218d2ad6d8b45c57f73d5c176245c303d3 Mon Sep 17 00:00:00 2001 From: Michael Solomon Date: Thu, 5 Oct 2023 00:01:12 +0300 Subject: [PATCH 3/4] fix --- src/interceptors/ClientRequest/NodeClientRequest.ts | 9 ++++++--- src/utils/nodeError.ts | 5 +++++ ...and-write.test.ts => http-req-end-then-write.test.ts} | 2 -- 3 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 src/utils/nodeError.ts rename test/modules/http/compliance/{http-req-end-and-write.test.ts => http-req-end-then-write.test.ts} (97%) diff --git a/src/interceptors/ClientRequest/NodeClientRequest.ts b/src/interceptors/ClientRequest/NodeClientRequest.ts index 5bce39aa..fa85f77f 100644 --- a/src/interceptors/ClientRequest/NodeClientRequest.ts +++ b/src/interceptors/ClientRequest/NodeClientRequest.ts @@ -20,6 +20,7 @@ import { toInteractiveRequest } from '../../utils/toInteractiveRequest' import { uuidv4 } from '../../utils/uuid' import { emitAsync } from '../../utils/emitAsync' import { getRawFetchHeaders } from '../../utils/getRawFetchHeaders' +import { NodeError } from '../../utils/nodeError' export type Protocol = 'http' | 'https' @@ -104,9 +105,11 @@ export class NodeClientRequest extends ClientRequest { } write(...args: ClientRequestWriteArgs): boolean { - // Fallback to native behavior to throw - if (this.destroyed || this.finished) { - return super.write(args) + if (this.isRequestSent) { + const err = new NodeError('write after end', 'ERR_STREAM_WRITE_AFTER_END') + process.nextTick(() => this.emit('error', err)) + + return false } const [chunk, encoding, callback] = normalizeClientRequestWriteArgs(args) diff --git a/src/utils/nodeError.ts b/src/utils/nodeError.ts new file mode 100644 index 00000000..2d27c69d --- /dev/null +++ b/src/utils/nodeError.ts @@ -0,0 +1,5 @@ +export class NodeError extends Error { + constructor(message: string, readonly code: string) { + super(message) + } +} \ No newline at end of file diff --git a/test/modules/http/compliance/http-req-end-and-write.test.ts b/test/modules/http/compliance/http-req-end-then-write.test.ts similarity index 97% rename from test/modules/http/compliance/http-req-end-and-write.test.ts rename to test/modules/http/compliance/http-req-end-then-write.test.ts index 9192e31c..ac48efac 100644 --- a/test/modules/http/compliance/http-req-end-and-write.test.ts +++ b/test/modules/http/compliance/http-req-end-then-write.test.ts @@ -28,8 +28,6 @@ it('emits the ERR_STREAM_WRITE_AFTER_END error when write after end given no moc const errorReceived = new DeferredPromise() req.on('error', (error) => { - console.log(error); - errorReceived.resolve(error) }) From ad6740674d5028c4b672e0d4b125b1d9cbde4c86 Mon Sep 17 00:00:00 2001 From: Michael Solomon Date: Fri, 1 Dec 2023 17:47:35 +0200 Subject: [PATCH 4/4] fix --- src/utils/nodeError.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/nodeError.ts b/src/utils/nodeError.ts index 2d27c69d..5b5f0a36 100644 --- a/src/utils/nodeError.ts +++ b/src/utils/nodeError.ts @@ -1,5 +1,5 @@ export class NodeError extends Error { - constructor(message: string, readonly code: string) { + constructor(readonly message: string, readonly code: string) { super(message) } } \ No newline at end of file