11import net from 'node:net'
22import { Readable , Writable } from 'node:stream'
33import { invariant } from 'outvariant'
4- import { Interceptor , INTERNAL_REQUEST_ID_HEADER_NAME } from '../../Interceptor'
4+ import { Interceptor } from '../../Interceptor'
55import { type HttpRequestEventMap } from '../../glossary'
66import { SocketInterceptor } from '../net'
77import { FetchResponse } from '../../utils/fetchUtils'
88import { HttpParser } from './http-parser'
99import { baseUrlFromConnectionOptions } from '../Socket/utils/baseUrlFromConnectionOptions'
10- import { MockSocket } from '../net/mock-socket'
1110import type { NetworkConnectionOptions } from '../net/utils/normalize-net-connect-args'
1211import { toBuffer } from './utils/to-buffer'
1312import { createRequestId } from '../../createRequestId'
@@ -81,32 +80,44 @@ export class HttpRequestInterceptor extends Interceptor<HttpRequestEventMap> {
8180 controller,
8281 emitter : this . emitter ,
8382 onResponse : async ( response ) => {
83+ if ( this . emitter . listenerCount ( 'response' ) > 0 ) {
84+ const responseClone = response . clone ( )
85+ process . nextTick ( ( ) => {
86+ emitAsync ( this . emitter , 'response' , {
87+ requestId,
88+ request,
89+ response : responseClone ,
90+ isMockedResponse : true ,
91+ } )
92+ } )
93+ }
94+
8495 await respondWith ( {
8596 socket,
8697 connectionOptions : options ,
8798 request,
8899 response,
89100 } )
90- await emitAsync ( this . emitter , 'response' , {
91- requestId,
92- request,
93- response,
94- isMockedResponse : true ,
95- } )
96101 } ,
97102 async onRequestError ( response ) {
103+ if ( this . emitter . listenerCount ( 'response' ) > 0 ) {
104+ const responseClone = response . clone ( )
105+ process . nextTick ( ( ) => {
106+ emitAsync ( this . emitter , 'response' , {
107+ requestId,
108+ request,
109+ response : responseClone ,
110+ isMockedResponse : true ,
111+ } )
112+ } )
113+ }
114+
98115 await respondWith ( {
99116 socket,
100117 connectionOptions : options ,
101118 request,
102119 response,
103120 } )
104- await emitAsync ( this . emitter , 'response' , {
105- requestId,
106- request,
107- response,
108- isMockedResponse : true ,
109- } )
110121 } ,
111122 onError ( error ) {
112123 if ( error instanceof Error ) {
@@ -116,22 +127,6 @@ export class HttpRequestInterceptor extends Interceptor<HttpRequestEventMap> {
116127 } )
117128
118129 if ( ! isRequestHandled ) {
119- // If the user didn't register any response listeners, no need to pay the
120- // price of routing the entire response message through the parser.
121- if ( this . emitter . listenerCount ( 'response' ) > 0 ) {
122- createHttpResponseParserStream ( {
123- socket,
124- onResponse : async ( response ) => {
125- await emitAsync ( this . emitter , 'response' , {
126- requestId,
127- request,
128- response,
129- isMockedResponse : false ,
130- } )
131- } ,
132- } )
133- }
134-
135130 const passthroughSocket = socket . passthrough ( )
136131
137132 /**
@@ -147,14 +142,39 @@ export class HttpRequestInterceptor extends Interceptor<HttpRequestEventMap> {
147142 passthroughSocket . parser = socket . parser
148143 // @ts -expect-error Node.js internals.
149144 passthroughSocket . parser . socket = passthroughSocket
145+
146+ // If the user didn't register any response listeners, no need to pay the
147+ // price of routing the entire response message through the parser.
148+ if ( this . emitter . listenerCount ( 'response' ) > 0 ) {
149+ const responseStream = createHttpResponseParserStream ( {
150+ onResponse : async ( response ) => {
151+ await emitAsync ( this . emitter , 'response' , {
152+ requestId,
153+ request,
154+ response,
155+ isMockedResponse : false ,
156+ } )
157+ } ,
158+ } )
159+
160+ passthroughSocket
161+ . on ( 'data' , ( chunk ) => responseStream . write ( chunk ) )
162+ . on ( 'close' , ( ) => responseStream . end ( ) )
163+ }
150164 }
151165 } ,
152166 } )
153167
154168 // Write the message header to the parser manually because it's already been written
155169 // on the socket so it won't get piped.
156170 requestParser . write ( toBuffer ( chunk , encoding ) )
157- socket . pipe ( requestParser )
171+
172+ socket
173+ . on ( 'write' , ( chunk , encoding , callback ) => {
174+ requestParser . write ( chunk , encoding , callback )
175+ } )
176+ . on ( 'finish' , ( ) => requestParser . end ( ) )
177+ . on ( 'error' , ( ) => requestParser . end ( ) )
158178 } )
159179 } )
160180 } )
@@ -211,13 +231,7 @@ function createHttpRequestParserStream(options: {
211231 * @note Provide the `read()` method so a `Readable` could be
212232 * used as the actual request body (the stream calls "read()").
213233 */
214- read ( ) {
215- // If the user attempts to read the request body,
216- // flush the write buffer to trigger the callbacks.
217- // This way, if the request stream ends in the write callback,
218- // it will indeed end correctly.
219- // flushWriteBuffer()
220- } ,
234+ read ( ) { } ,
221235 } )
222236
223237 const request = new Request ( url , {
@@ -254,25 +268,18 @@ function createHttpRequestParserStream(options: {
254268 } ,
255269 } )
256270
257- const parserStream = new Writable ( {
271+ return new Writable ( {
258272 write ( chunk , encoding , callback ) {
259273 parser . execute ( toBuffer ( chunk , encoding ) )
260274 callback ( )
261275 } ,
262276 } )
263-
264- parserStream
265- . once ( 'finish' , ( ) => parser . free ( ) )
266- . once ( 'close' , ( ) => parser . free ( ) )
267-
268- return parserStream
269277}
270278
271279function createHttpResponseParserStream ( options : {
272- socket : MockSocket
273280 onResponse : ( response : Response ) => void
274281} ) {
275- const { socket , onResponse } = options
282+ const { onResponse } = options
276283 const responseRawHeadersBuffer : Array < string > = [ ]
277284 let responseBodyStream : Readable | undefined
278285
@@ -323,11 +330,12 @@ function createHttpResponseParserStream(options: {
323330 } ,
324331 } )
325332
326- socket
327- . on ( 'push' , ( chunk , encoding ) => {
333+ return new Writable ( {
334+ write ( chunk , encoding , callback ) {
328335 parser . execute ( toBuffer ( chunk , encoding ) )
329- } )
330- . once ( 'close' , ( ) => parser . free ( ) )
336+ callback ( )
337+ } ,
338+ } )
331339}
332340
333341/**
0 commit comments