@mswjs/interceptors 0.42.4 → 0.42.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/interceptors/fetch/web.js +1 -1
- package/lib/browser/presets/browser.js +1 -1
- package/lib/browser/{web-CdcYFjgm.js → web-DUlFZEtz.js} +58 -3
- package/lib/browser/web-DUlFZEtz.js.map +1 -0
- package/lib/node/{fetch-utils-Tm5LbwBe.js → fetch-utils-D-_xeRlK.js} +2 -2
- package/lib/node/{fetch-utils-Tm5LbwBe.js.map → fetch-utils-D-_xeRlK.js.map} +1 -1
- package/lib/node/index.js +1 -1
- package/lib/node/interceptors/ClientRequest/index.js +1 -1
- package/lib/node/interceptors/XMLHttpRequest/node.js +2 -2
- package/lib/node/interceptors/fetch/node.js +2 -2
- package/lib/node/interceptors/http/index.js +1 -1
- package/lib/node/interceptors/net/index.d.ts +7 -0
- package/lib/node/interceptors/net/index.js +1 -1
- package/lib/node/{net-DkiHxhQF.js → net-Bh16MP4u.js} +40 -14
- package/lib/node/net-Bh16MP4u.js.map +1 -0
- package/lib/node/remote-http-interceptor.js +2 -2
- package/lib/node/{source-BFZ6wg4P.js → source-DHVO1vzq.js} +297 -240
- package/lib/node/source-DHVO1vzq.js.map +1 -0
- package/package.json +1 -1
- package/src/interceptors/fetch/web.ts +11 -2
- package/src/interceptors/http/source.ts +341 -324
- package/src/interceptors/net/socket-controller.ts +92 -57
- package/src/utils/clone-response.ts +72 -0
- package/lib/browser/web-CdcYFjgm.js.map +0 -1
- package/lib/node/net-DkiHxhQF.js.map +0 -1
- package/lib/node/source-BFZ6wg4P.js.map +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as FetchInterceptor } from "../../web-
|
|
1
|
+
import { t as FetchInterceptor } from "../../web-DUlFZEtz.js";
|
|
2
2
|
export { FetchInterceptor };
|
|
@@ -112,6 +112,56 @@ function decompressResponse(response) {
|
|
|
112
112
|
return decompressionStream.readable;
|
|
113
113
|
}
|
|
114
114
|
//#endregion
|
|
115
|
+
//#region src/utils/clone-response.ts
|
|
116
|
+
/** Clone for observers without letting their unread body block caller cancellation. */
|
|
117
|
+
function cloneResponse(response) {
|
|
118
|
+
const clone = FetchResponse.clone(response);
|
|
119
|
+
if (!response.body || !clone.body) return [response, clone];
|
|
120
|
+
const observer = wrapResponse(clone);
|
|
121
|
+
return [wrapResponse(response, observer.cancel).response, observer.response];
|
|
122
|
+
}
|
|
123
|
+
function wrapResponse(response, onCancel) {
|
|
124
|
+
const body = response.body;
|
|
125
|
+
const reader = body.getReader();
|
|
126
|
+
const cancel = (reason) => {
|
|
127
|
+
return body.locked ? reader.cancel(reason) : body.cancel(reason);
|
|
128
|
+
};
|
|
129
|
+
const wrappedResponse = new FetchResponse(new ReadableStream({
|
|
130
|
+
async pull(controller) {
|
|
131
|
+
try {
|
|
132
|
+
const { done, value } = await reader.read();
|
|
133
|
+
if (done) {
|
|
134
|
+
controller.close();
|
|
135
|
+
reader.releaseLock();
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
controller.enqueue(value);
|
|
139
|
+
} catch (error) {
|
|
140
|
+
controller.error(error);
|
|
141
|
+
reader.releaseLock();
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
async cancel(reason) {
|
|
145
|
+
try {
|
|
146
|
+
const cancellation = cancel(reason);
|
|
147
|
+
if (onCancel) await Promise.all([cancellation, onCancel(reason)]);
|
|
148
|
+
else cancellation.catch(() => {});
|
|
149
|
+
} finally {
|
|
150
|
+
reader.releaseLock();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}, { highWaterMark: 0 }), response);
|
|
154
|
+
copyRawHeaders(response.headers, wrappedResponse.headers);
|
|
155
|
+
Object.defineProperties(wrappedResponse, {
|
|
156
|
+
type: { value: response.type },
|
|
157
|
+
redirected: { value: response.redirected }
|
|
158
|
+
});
|
|
159
|
+
return {
|
|
160
|
+
response: wrappedResponse,
|
|
161
|
+
cancel
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
//#endregion
|
|
115
165
|
//#region src/interceptors/fetch/web.ts
|
|
116
166
|
const logger = createLogger("fetch");
|
|
117
167
|
/**
|
|
@@ -153,7 +203,7 @@ var FetchInterceptor = class extends Interceptor {
|
|
|
153
203
|
logger.verbose("original fetch performed %o", originalResponse);
|
|
154
204
|
if (this.emitter.listenerCount("response") > 0) {
|
|
155
205
|
logger.verbose("emitting the \"response\" event");
|
|
156
|
-
const responseClone =
|
|
206
|
+
const [response, responseClone] = cloneResponse(originalResponse);
|
|
157
207
|
await this.emitter.emitAsPromise(new HttpResponseEvent({
|
|
158
208
|
initiator: requestCloneForResponseEvent,
|
|
159
209
|
request: requestCloneForResponseEvent,
|
|
@@ -161,6 +211,8 @@ var FetchInterceptor = class extends Interceptor {
|
|
|
161
211
|
response: responseClone,
|
|
162
212
|
responseType: "original"
|
|
163
213
|
}));
|
|
214
|
+
responsePromise.resolve(response);
|
|
215
|
+
return;
|
|
164
216
|
}
|
|
165
217
|
responsePromise.resolve(originalResponse);
|
|
166
218
|
},
|
|
@@ -199,13 +251,16 @@ var FetchInterceptor = class extends Interceptor {
|
|
|
199
251
|
}
|
|
200
252
|
if (this.emitter.listenerCount("response") > 0) {
|
|
201
253
|
logger.verbose("emitting the \"response\" event");
|
|
254
|
+
const [callerResponse, responseClone] = cloneResponse(response);
|
|
202
255
|
await this.emitter.emitAsPromise(new HttpResponseEvent({
|
|
203
256
|
initiator: request,
|
|
204
|
-
response:
|
|
257
|
+
response: responseClone,
|
|
205
258
|
responseType: "mock",
|
|
206
259
|
request,
|
|
207
260
|
requestId
|
|
208
261
|
}));
|
|
262
|
+
responsePromise.resolve(callerResponse);
|
|
263
|
+
return;
|
|
209
264
|
}
|
|
210
265
|
responsePromise.resolve(response);
|
|
211
266
|
},
|
|
@@ -245,4 +300,4 @@ var FetchInterceptor = class extends Interceptor {
|
|
|
245
300
|
//#endregion
|
|
246
301
|
export { FetchInterceptor as t };
|
|
247
302
|
|
|
248
|
-
//# sourceMappingURL=web-
|
|
303
|
+
//# sourceMappingURL=web-DUlFZEtz.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-DUlFZEtz.js","names":[],"sources":["../../src/interceptors/fetch/utils/create-network-error.ts","../../src/interceptors/fetch/utils/follow-redirect.ts","../../src/interceptors/fetch/utils/brotli-decompress.browser.ts","../../src/interceptors/fetch/utils/decompression.ts","../../src/utils/clone-response.ts","../../src/interceptors/fetch/web.ts"],"sourcesContent":["export function createNetworkError(cause?: unknown) {\n return Object.assign(new TypeError('Failed to fetch'), {\n cause,\n })\n}\n","import { createNetworkError } from './create-network-error'\n\nconst REQUEST_BODY_HEADERS = [\n 'content-encoding',\n 'content-language',\n 'content-location',\n 'content-type',\n 'content-length',\n]\n\nconst kRedirectCount = Symbol('kRedirectCount')\n\n/**\n * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/index.js#L1210\n */\nexport async function followFetchRedirect(\n request: Request,\n response: Response\n): Promise<Response> {\n if (response.status !== 303 && request.body != null) {\n return Promise.reject(createNetworkError())\n }\n\n const requestUrl = new URL(request.url)\n\n let locationUrl: URL\n try {\n // If the location is a relative URL, use the request URL as the base URL.\n locationUrl = new URL(response.headers.get('location')!, request.url) \n } catch (error) {\n return Promise.reject(createNetworkError(error))\n }\n\n if (\n !(locationUrl.protocol === 'http:' || locationUrl.protocol === 'https:')\n ) {\n return Promise.reject(\n createNetworkError('URL scheme must be a HTTP(S) scheme')\n )\n }\n\n if (Reflect.get(request, kRedirectCount) > 20) {\n return Promise.reject(createNetworkError('redirect count exceeded'))\n }\n\n Object.defineProperty(request, kRedirectCount, {\n value: (Reflect.get(request, kRedirectCount) || 0) + 1,\n })\n\n if (\n request.mode === 'cors' &&\n (locationUrl.username || locationUrl.password) &&\n !sameOrigin(requestUrl, locationUrl)\n ) {\n return Promise.reject(\n createNetworkError('cross origin not allowed for request mode \"cors\"')\n )\n }\n\n const requestInit: RequestInit = {}\n\n if (\n ([301, 302].includes(response.status) && request.method === 'POST') ||\n (response.status === 303 && !['HEAD', 'GET'].includes(request.method))\n ) {\n requestInit.method = 'GET'\n requestInit.body = null\n\n REQUEST_BODY_HEADERS.forEach((headerName) => {\n request.headers.delete(headerName)\n })\n }\n\n if (!sameOrigin(requestUrl, locationUrl)) {\n request.headers.delete('authorization')\n request.headers.delete('proxy-authorization')\n request.headers.delete('cookie')\n request.headers.delete('host')\n }\n\n /**\n * @note Undici \"safely\" extracts the request body.\n * I suspect we cannot dispatch this request again\n * since its body has been read and the stream is locked.\n */\n\n requestInit.headers = request.headers\n const finalResponse = await fetch(new Request(locationUrl, requestInit))\n Object.defineProperty(finalResponse, 'redirected', {\n value: true,\n configurable: true,\n })\n\n return finalResponse\n}\n\n/**\n * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/util.js#L761\n */\nfunction sameOrigin(left: URL, right: URL): boolean {\n if (left.origin === right.origin && left.origin === 'null') {\n return true\n }\n\n if (\n left.protocol === right.protocol &&\n left.hostname === right.hostname &&\n left.port === right.port\n ) {\n return true\n }\n\n return false\n}\n","export class BrotliDecompressionStream extends TransformStream {\n constructor() {\n console.warn(\n '[Interceptors]: Brotli decompression of response streams is not supported in the browser'\n )\n\n super({\n transform(chunk, controller) {\n // Keep the stream as passthrough, it does nothing.\n controller.enqueue(chunk)\n },\n })\n }\n}\n","// Import from an internal alias that resolves to different modules\n// depending on the environment. This way, we can keep the fetch interceptor\n// intact while using different strategies for Brotli decompression.\nimport { BrotliDecompressionStream } from 'internal:brotli-decompress'\n\nclass PipelineStream extends TransformStream {\n constructor(\n transformStreams: Array<TransformStream>,\n ...strategies: Array<QueuingStrategy>\n ) {\n super({}, ...strategies)\n\n const readable = [super.readable as any, ...transformStreams].reduce(\n (readable, transform) => readable.pipeThrough(transform)\n )\n\n Object.defineProperty(this, 'readable', {\n get() {\n return readable\n },\n })\n }\n}\n\nexport function parseContentEncoding(contentEncoding: string): Array<string> {\n return contentEncoding\n .toLowerCase()\n .split(',')\n .map((coding) => coding.trim())\n}\n\nfunction createDecompressionStream(\n contentEncoding: string\n): TransformStream | null {\n if (contentEncoding === '') {\n return null\n }\n\n const codings = parseContentEncoding(contentEncoding)\n\n if (codings.length === 0) {\n return null\n }\n\n const transformers = codings.reduceRight<Array<TransformStream>>(\n (transformers, coding) => {\n if (coding === 'gzip' || coding === 'x-gzip') {\n return transformers.concat(new DecompressionStream('gzip'))\n } else if (coding === 'deflate') {\n return transformers.concat(new DecompressionStream('deflate'))\n } else if (coding === 'br') {\n return transformers.concat(new BrotliDecompressionStream())\n } else {\n transformers.length = 0\n }\n\n return transformers\n },\n []\n )\n\n return new PipelineStream(transformers)\n}\n\nexport function decompressResponse(\n response: Response\n): ReadableStream<any> | null {\n if (response.body === null) {\n return null\n }\n\n const decompressionStream = createDecompressionStream(\n response.headers.get('content-encoding') || ''\n )\n\n if (!decompressionStream) {\n return null\n }\n\n // Use `pipeTo` and return the decompression stream's readable\n // instead of `pipeThrough` because that will lock the original\n // response stream, making it unusable as the input to Response.\n response.body.pipeTo(decompressionStream.writable)\n return decompressionStream.readable\n}\n","import { FetchResponse } from './fetch-utils'\nimport { copyRawHeaders } from '../interceptors/ClientRequest/utils/record-raw-headers'\n\n/** Clone for observers without letting their unread body block caller cancellation. */\nexport function cloneResponse(response: Response): [Response, Response] {\n const clone = FetchResponse.clone(response)\n\n if (!response.body || !clone.body) {\n return [response, clone]\n }\n\n const observer = wrapResponse(clone)\n const caller = wrapResponse(response, observer.cancel)\n\n return [caller.response, observer.response]\n}\n\nfunction wrapResponse(\n response: Response,\n onCancel?: (reason: unknown) => Promise<void>\n) {\n const body = response.body!\n const reader = body.getReader()\n const cancel = (reason: unknown) => {\n return body.locked ? reader.cancel(reason) : body.cancel(reason)\n }\n const stream = new ReadableStream<Uint8Array>(\n {\n async pull(controller) {\n try {\n const { done, value } = await reader.read()\n\n if (done) {\n controller.close()\n reader.releaseLock()\n return\n }\n\n controller.enqueue(value)\n } catch (error) {\n controller.error(error)\n reader.releaseLock()\n }\n },\n async cancel(reason) {\n try {\n const cancellation = cancel(reason)\n\n if (onCancel) {\n // Caller cancellation owns both branches.\n await Promise.all([cancellation, onCancel(reason)])\n } else {\n // An observer must not wait for the caller to consume its branch:\n // Response delivery is still waiting for this listener to finish.\n void cancellation.catch(() => {})\n }\n } finally {\n reader.releaseLock()\n }\n },\n },\n { highWaterMark: 0 }\n )\n const wrappedResponse = new FetchResponse(stream, response)\n copyRawHeaders(response.headers, wrappedResponse.headers)\n Object.defineProperties(wrappedResponse, {\n type: { value: response.type },\n redirected: { value: response.redirected },\n })\n\n return { response: wrappedResponse, cancel }\n}\n","import { until } from '@open-draft/until'\nimport { HttpResponseEvent, type HttpRequestEventMap } from '../../events/http'\nimport { RequestController } from '../../request-controller'\nimport { handleRequest } from '../../utils/handle-request'\nimport { createRequestId } from '../../create-request-id'\nimport { createNetworkError } from './utils/create-network-error'\nimport { followFetchRedirect } from './utils/follow-redirect'\nimport { decompressResponse } from './utils/decompression'\nimport { cloneResponse } from '../../utils/clone-response'\nimport { hasConfigurableGlobal } from '../../utils/has-configurable-global'\nimport { FetchResponse } from '../../utils/fetch-utils'\nimport { isResponseError } from '../../utils/response-utils'\nimport { patchesRegistry } from '../../utils/patches-registry'\nimport { copyRawHeaders } from '../ClientRequest/utils/record-raw-headers'\nimport { Interceptor } from '../../interceptor'\nimport { createLogger } from '../../utils/logger'\n\nconst logger = createLogger('fetch')\n\n/**\n * Interceptor for `fetch` requests in the browser.\n */\nexport class FetchInterceptor extends Interceptor<HttpRequestEventMap> {\n static symbol = Symbol.for('fetch-interceptor')\n\n protected predicate() {\n return hasConfigurableGlobal('fetch')\n }\n\n protected async setup() {\n logger.verbose('patching global fetch...')\n\n this.subscriptions.push(\n patchesRegistry.applyPatch(globalThis, 'fetch', (realFetch) => {\n return async (input, init) => {\n const requestId = createRequestId()\n\n /**\n * @note Resolve potentially relative request URL\n * against the present `location`. This is mainly\n * for native `fetch` in JSDOM.\n * @see https://github.com/mswjs/msw/issues/1625\n */\n const resolvedInput =\n typeof input === 'string' &&\n typeof location !== 'undefined' &&\n !URL.canParse(input)\n ? new URL(input, location.href)\n : input\n\n const request = new Request(resolvedInput, init)\n\n const responsePromise = Promise.withResolvers<Response>()\n\n const controller = new RequestController(\n request,\n {\n passthrough: async () => {\n logger.verbose('performing request as-is')\n\n /**\n * @note Clone the request instance right before performing it.\n * This preserves any modifications made to the intercepted request\n * in the \"request\" listener. This also allows the user to read the\n * request body in the \"response\" listener (otherwise \"unusable\").\n */\n const requestCloneForResponseEvent = request.clone()\n\n // Perform the intercepted request as-is.\n const [responseError, originalResponse] = await until(() =>\n realFetch(request)\n )\n\n if (responseError) {\n return responsePromise.reject(responseError)\n }\n\n logger.verbose('original fetch performed %o', originalResponse)\n\n if (this.emitter.listenerCount('response') > 0) {\n logger.verbose('emitting the \"response\" event')\n\n const [response, responseClone] = cloneResponse(originalResponse)\n await this.emitter.emitAsPromise(\n new HttpResponseEvent({\n initiator: requestCloneForResponseEvent,\n request: requestCloneForResponseEvent,\n requestId,\n response: responseClone,\n responseType: 'original',\n })\n )\n\n responsePromise.resolve(response)\n return\n }\n\n // Resolve the response promise with the original response\n // since the `fetch()` return this internal promise.\n responsePromise.resolve(originalResponse)\n },\n respondWith: async (rawResponse) => {\n // Handle mocked `Response.error()` (i.e. request errors).\n if (isResponseError(rawResponse)) {\n logger.verbose('request errored %o', {\n response: rawResponse,\n })\n responsePromise.reject(createNetworkError(rawResponse))\n return\n }\n\n // Decompress the mocked response body, if applicable.\n const decompressedStream = decompressResponse(rawResponse)\n const response = new FetchResponse(\n decompressedStream || rawResponse.body,\n {\n url: request.url,\n status: rawResponse.status,\n statusText: rawResponse.statusText,\n headers: rawResponse.headers,\n }\n )\n\n copyRawHeaders(rawResponse.headers, response.headers)\n\n /**\n * Undici's handling of following redirect responses.\n * Treat the \"manual\" redirect mode as a regular mocked response.\n * This way, the client can manually follow the redirect it receives.\n * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/index.js#L1173\n */\n if (FetchResponse.isRedirectResponse(response.status)) {\n // Reject the request promise if its `redirect` is set to `error`\n // and it receives a mocked redirect response.\n if (request.redirect === 'error') {\n responsePromise.reject(\n createNetworkError('unexpected redirect')\n )\n return\n }\n\n if (request.redirect === 'follow') {\n followFetchRedirect(request, response).then(\n (response) => {\n responsePromise.resolve(response)\n },\n (reason) => {\n responsePromise.reject(reason)\n }\n )\n return\n }\n }\n\n if (this.emitter.listenerCount('response') > 0) {\n logger.verbose('emitting the \"response\" event')\n\n const [callerResponse, responseClone] = cloneResponse(response)\n\n // Await the response listeners to finish before resolving\n // the response promise. This ensures all your logic finishes\n // before the interceptor resolves the pending response.\n await this.emitter.emitAsPromise(\n new HttpResponseEvent({\n initiator: request,\n // Clone the mocked response for the \"response\" event listener.\n // This way, the listener can read the response and not lock its body\n // for the actual fetch consumer.\n response: responseClone,\n responseType: 'mock',\n request,\n requestId,\n })\n )\n\n responsePromise.resolve(callerResponse)\n return\n }\n\n responsePromise.resolve(response)\n },\n errorWith: (reason) => {\n logger.verbose('request aborted %o', { reason })\n responsePromise.reject(reason)\n },\n },\n {\n logger,\n requestId,\n }\n )\n\n logger.verbose('awaiting request resolution')\n\n logger.verbose(\n 'emitting the \"request\" event for %s listener(s)...',\n this.emitter.listenerCount('request')\n )\n\n /**\n * @note Give the consumer a chance to abort the request before\n * it is dispatched. Fetch queues the request processing as a\n * task, so a signal aborted synchronously after `fetch()` must\n * prevent the request from ever reaching the \"request\" listeners.\n * Without this, the first listener is invoked synchronously\n * within the `fetch()` call itself.\n */\n await Promise.resolve()\n\n await handleRequest({\n initiator: request,\n request,\n requestId,\n emitter: this.emitter,\n controller,\n logger,\n })\n\n return responsePromise.promise\n }\n })\n )\n\n logger.verbose('global fetch patched: %s', globalThis.fetch.name)\n }\n}\n"],"mappings":";;;;;;AAAA,SAAgB,mBAAmB,OAAiB;CAClD,OAAO,OAAO,uBAAO,IAAI,UAAU,iBAAiB,GAAG,EACrD,MACF,CAAC;AACH;;;ACFA,MAAM,uBAAuB;CAC3B;CACA;CACA;CACA;CACA;AACF;AAEA,MAAM,iBAAiB,OAAO,gBAAgB;;;;AAK9C,eAAsB,oBACpB,SACA,UACmB;CACnB,IAAI,SAAS,WAAW,OAAO,QAAQ,QAAQ,MAC7C,OAAO,QAAQ,OAAO,mBAAmB,CAAC;CAG5C,MAAM,aAAa,IAAI,IAAI,QAAQ,GAAG;CAEtC,IAAI;CACJ,IAAI;EAEF,cAAc,IAAI,IAAI,SAAS,QAAQ,IAAI,UAAU,GAAI,QAAQ,GAAG;CACtE,SAAS,OAAO;EACd,OAAO,QAAQ,OAAO,mBAAmB,KAAK,CAAC;CACjD;CAEA,IACE,EAAE,YAAY,aAAa,WAAW,YAAY,aAAa,WAE/D,OAAO,QAAQ,OACb,mBAAmB,qCAAqC,CAC1D;CAGF,IAAI,QAAQ,IAAI,SAAS,cAAc,IAAI,IACzC,OAAO,QAAQ,OAAO,mBAAmB,yBAAyB,CAAC;CAGrE,OAAO,eAAe,SAAS,gBAAgB,EAC7C,QAAQ,QAAQ,IAAI,SAAS,cAAc,KAAK,KAAK,EACvD,CAAC;CAED,IACE,QAAQ,SAAS,WAChB,YAAY,YAAY,YAAY,aACrC,CAAC,WAAW,YAAY,WAAW,GAEnC,OAAO,QAAQ,OACb,mBAAmB,oDAAkD,CACvE;CAGF,MAAM,cAA2B,CAAC;CAElC,IACG,CAAC,KAAK,GAAG,CAAC,CAAC,SAAS,SAAS,MAAM,KAAK,QAAQ,WAAW,UAC3D,SAAS,WAAW,OAAO,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,SAAS,QAAQ,MAAM,GACpE;EACA,YAAY,SAAS;EACrB,YAAY,OAAO;EAEnB,qBAAqB,SAAS,eAAe;GAC3C,QAAQ,QAAQ,OAAO,UAAU;EACnC,CAAC;CACH;CAEA,IAAI,CAAC,WAAW,YAAY,WAAW,GAAG;EACxC,QAAQ,QAAQ,OAAO,eAAe;EACtC,QAAQ,QAAQ,OAAO,qBAAqB;EAC5C,QAAQ,QAAQ,OAAO,QAAQ;EAC/B,QAAQ,QAAQ,OAAO,MAAM;CAC/B;;;;;;CAQA,YAAY,UAAU,QAAQ;CAC9B,MAAM,gBAAgB,MAAM,MAAM,IAAI,QAAQ,aAAa,WAAW,CAAC;CACvE,OAAO,eAAe,eAAe,cAAc;EACjD,OAAO;EACP,cAAc;CAChB,CAAC;CAED,OAAO;AACT;;;;AAKA,SAAS,WAAW,MAAW,OAAqB;CAClD,IAAI,KAAK,WAAW,MAAM,UAAU,KAAK,WAAW,QAClD,OAAO;CAGT,IACE,KAAK,aAAa,MAAM,YACxB,KAAK,aAAa,MAAM,YACxB,KAAK,SAAS,MAAM,MAEpB,OAAO;CAGT,OAAO;AACT;;;ACjHA,IAAa,4BAAb,cAA+C,gBAAgB;CAC7D,cAAc;EACZ,QAAQ,KACN,0FACF;EAEA,MAAM,EACJ,UAAU,OAAO,YAAY;GAE3B,WAAW,QAAQ,KAAK;EAC1B,EACF,CAAC;CACH;AACF;;;ACRA,IAAM,iBAAN,cAA6B,gBAAgB;CAC3C,YACE,kBACA,GAAG,YACH;EACA,MAAM,CAAC,GAAG,GAAG,UAAU;EAEvB,MAAM,WAAW,CAAC,MAAM,UAAiB,GAAG,gBAAgB,CAAC,CAAC,QAC3D,UAAU,cAAc,SAAS,YAAY,SAAS,CACzD;EAEA,OAAO,eAAe,MAAM,YAAY,EACtC,MAAM;GACJ,OAAO;EACT,EACF,CAAC;CACH;AACF;AAEA,SAAgB,qBAAqB,iBAAwC;CAC3E,OAAO,gBACJ,YAAY,CAAC,CACb,MAAM,GAAG,CAAC,CACV,KAAK,WAAW,OAAO,KAAK,CAAC;AAClC;AAEA,SAAS,0BACP,iBACwB;CACxB,IAAI,oBAAoB,IACtB,OAAO;CAGT,MAAM,UAAU,qBAAqB,eAAe;CAEpD,IAAI,QAAQ,WAAW,GACrB,OAAO;CAoBT,OAAO,IAAI,eAjBU,QAAQ,aAC1B,cAAc,WAAW;EACxB,IAAI,WAAW,UAAU,WAAW,UAClC,OAAO,aAAa,OAAO,IAAI,oBAAoB,MAAM,CAAC;OACrD,IAAI,WAAW,WACpB,OAAO,aAAa,OAAO,IAAI,oBAAoB,SAAS,CAAC;OACxD,IAAI,WAAW,MACpB,OAAO,aAAa,OAAO,IAAI,0BAA0B,CAAC;OAE1D,aAAa,SAAS;EAGxB,OAAO;CACT,GACA,CAAC,CAGuB,CAAY;AACxC;AAEA,SAAgB,mBACd,UAC4B;CAC5B,IAAI,SAAS,SAAS,MACpB,OAAO;CAGT,MAAM,sBAAsB,0BAC1B,SAAS,QAAQ,IAAI,kBAAkB,KAAK,EAC9C;CAEA,IAAI,CAAC,qBACH,OAAO;CAMT,SAAS,KAAK,OAAO,oBAAoB,QAAQ;CACjD,OAAO,oBAAoB;AAC7B;;;;AChFA,SAAgB,cAAc,UAA0C;CACtE,MAAM,QAAQ,cAAc,MAAM,QAAQ;CAE1C,IAAI,CAAC,SAAS,QAAQ,CAAC,MAAM,MAC3B,OAAO,CAAC,UAAU,KAAK;CAGzB,MAAM,WAAW,aAAa,KAAK;CAGnC,OAAO,CAFQ,aAAa,UAAU,SAAS,MAElC,CAAC,CAAC,UAAU,SAAS,QAAQ;AAC5C;AAEA,SAAS,aACP,UACA,UACA;CACA,MAAM,OAAO,SAAS;CACtB,MAAM,SAAS,KAAK,UAAU;CAC9B,MAAM,UAAU,WAAoB;EAClC,OAAO,KAAK,SAAS,OAAO,OAAO,MAAM,IAAI,KAAK,OAAO,MAAM;CACjE;CAsCA,MAAM,kBAAkB,IAAI,cAAc,IArCvB,eACjB;EACE,MAAM,KAAK,YAAY;GACrB,IAAI;IACF,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,KAAK;IAE1C,IAAI,MAAM;KACR,WAAW,MAAM;KACjB,OAAO,YAAY;KACnB;IACF;IAEA,WAAW,QAAQ,KAAK;GAC1B,SAAS,OAAO;IACd,WAAW,MAAM,KAAK;IACtB,OAAO,YAAY;GACrB;EACF;EACA,MAAM,OAAO,QAAQ;GACnB,IAAI;IACF,MAAM,eAAe,OAAO,MAAM;IAElC,IAAI,UAEF,MAAM,QAAQ,IAAI,CAAC,cAAc,SAAS,MAAM,CAAC,CAAC;SAIlD,aAAkB,YAAY,CAAC,CAAC;GAEpC,UAAU;IACR,OAAO,YAAY;GACrB;EACF;CACF,GACA,EAAE,eAAe,EAAE,CAE0B,GAAG,QAAQ;CAC1D,eAAe,SAAS,SAAS,gBAAgB,OAAO;CACxD,OAAO,iBAAiB,iBAAiB;EACvC,MAAM,EAAE,OAAO,SAAS,KAAK;EAC7B,YAAY,EAAE,OAAO,SAAS,WAAW;CAC3C,CAAC;CAED,OAAO;EAAE,UAAU;EAAiB;CAAO;AAC7C;;;ACtDA,MAAM,SAAS,aAAa,OAAO;;;;AAKnC,IAAa,mBAAb,cAAsC,YAAiC;;EACrD,KAAA,SAAA,OAAO,IAAI,mBAAmB;;CAE9C,YAAsB;EACpB,OAAO,sBAAsB,OAAO;CACtC;CAEA,MAAgB,QAAQ;EACtB,OAAO,QAAQ,0BAA0B;EAEzC,KAAK,cAAc,KACjB,gBAAgB,WAAW,YAAY,UAAU,cAAc;GAC7D,OAAO,OAAO,OAAO,SAAS;IAC5B,MAAM,YAAY,gBAAgB;;;;;;;IAQlC,MAAM,gBACJ,OAAO,UAAU,YACjB,OAAO,aAAa,eACpB,CAAC,IAAI,SAAS,KAAK,IACf,IAAI,IAAI,OAAO,SAAS,IAAI,IAC5B;IAEN,MAAM,UAAU,IAAI,QAAQ,eAAe,IAAI;IAE/C,MAAM,kBAAkB,QAAQ,cAAwB;IAExD,MAAM,aAAa,IAAI,kBACrB,SACA;KACE,aAAa,YAAY;MACvB,OAAO,QAAQ,0BAA0B;;;;;;;MAQzC,MAAM,+BAA+B,QAAQ,MAAM;MAGnD,MAAM,CAAC,eAAe,oBAAoB,MAAM,YAC9C,UAAU,OAAO,CACnB;MAEA,IAAI,eACF,OAAO,gBAAgB,OAAO,aAAa;MAG7C,OAAO,QAAQ,+BAA+B,gBAAgB;MAE9D,IAAI,KAAK,QAAQ,cAAc,UAAU,IAAI,GAAG;OAC9C,OAAO,QAAQ,iCAA+B;OAE9C,MAAM,CAAC,UAAU,iBAAiB,cAAc,gBAAgB;OAChE,MAAM,KAAK,QAAQ,cACjB,IAAI,kBAAkB;QACpB,WAAW;QACX,SAAS;QACT;QACA,UAAU;QACV,cAAc;OAChB,CAAC,CACH;OAEA,gBAAgB,QAAQ,QAAQ;OAChC;MACF;MAIA,gBAAgB,QAAQ,gBAAgB;KAC1C;KACA,aAAa,OAAO,gBAAgB;MAElC,IAAI,gBAAgB,WAAW,GAAG;OAChC,OAAO,QAAQ,sBAAsB,EACnC,UAAU,YACZ,CAAC;OACD,gBAAgB,OAAO,mBAAmB,WAAW,CAAC;OACtD;MACF;MAIA,MAAM,WAAW,IAAI,cADM,mBAAmB,WAE3B,KAAK,YAAY,MAClC;OACE,KAAK,QAAQ;OACb,QAAQ,YAAY;OACpB,YAAY,YAAY;OACxB,SAAS,YAAY;MACvB,CACF;MAEA,eAAe,YAAY,SAAS,SAAS,OAAO;;;;;;;MAQpD,IAAI,cAAc,mBAAmB,SAAS,MAAM,GAAG;OAGrD,IAAI,QAAQ,aAAa,SAAS;QAChC,gBAAgB,OACd,mBAAmB,qBAAqB,CAC1C;QACA;OACF;OAEA,IAAI,QAAQ,aAAa,UAAU;QACjC,oBAAoB,SAAS,QAAQ,CAAC,CAAC,MACpC,aAAa;SACZ,gBAAgB,QAAQ,QAAQ;QAClC,IACC,WAAW;SACV,gBAAgB,OAAO,MAAM;QAC/B,CACF;QACA;OACF;MACF;MAEA,IAAI,KAAK,QAAQ,cAAc,UAAU,IAAI,GAAG;OAC9C,OAAO,QAAQ,iCAA+B;OAE9C,MAAM,CAAC,gBAAgB,iBAAiB,cAAc,QAAQ;OAK9D,MAAM,KAAK,QAAQ,cACjB,IAAI,kBAAkB;QACpB,WAAW;QAIX,UAAU;QACV,cAAc;QACd;QACA;OACF,CAAC,CACH;OAEA,gBAAgB,QAAQ,cAAc;OACtC;MACF;MAEA,gBAAgB,QAAQ,QAAQ;KAClC;KACA,YAAY,WAAW;MACrB,OAAO,QAAQ,sBAAsB,EAAE,OAAO,CAAC;MAC/C,gBAAgB,OAAO,MAAM;KAC/B;IACF,GACA;KACE;KACA;IACF,CACF;IAEA,OAAO,QAAQ,6BAA6B;IAE5C,OAAO,QACL,wDACA,KAAK,QAAQ,cAAc,SAAS,CACtC;;;;;;;;;IAUA,MAAM,QAAQ,QAAQ;IAEtB,MAAM,cAAc;KAClB,WAAW;KACX;KACA;KACA,SAAS,KAAK;KACd;KACA;IACF,CAAC;IAED,OAAO,gBAAgB;GACzB;EACF,CAAC,CACH;EAEA,OAAO,QAAQ,4BAA4B,WAAW,MAAM,IAAI;CAClE;AACF"}
|
|
@@ -552,6 +552,6 @@ var FetchResponse = class FetchResponse extends Response {
|
|
|
552
552
|
}
|
|
553
553
|
};
|
|
554
554
|
//#endregion
|
|
555
|
-
export { isResponseError as a, isObject as c,
|
|
555
|
+
export { isResponseError as a, isObject as c, recordRawFetchHeaders as d, RequestController as f, getErrorResponse as i, copyRawHeaders as l, FetchResponse as n, isResponseLike as o, InterceptorError as p, createServerErrorResponse as r, kErrorResponse as s, FetchRequest as t, getRawFetchHeaders as u };
|
|
556
556
|
|
|
557
|
-
//# sourceMappingURL=fetch-utils-
|
|
557
|
+
//# sourceMappingURL=fetch-utils-D-_xeRlK.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-utils-Tm5LbwBe.js","names":["#handled","#resolveProperty","#setInternalProperty"],"sources":["../../src/interceptor-error.ts","../../src/request-controller.ts","../../src/interceptors/ClientRequest/utils/record-raw-headers.ts","../../src/utils/get-value-by-symbol.ts","../../src/utils/is-object.ts","../../src/utils/is-property-accessible.ts","../../src/utils/response-utils.ts","../../src/utils/fetch-utils.ts"],"sourcesContent":["export class InterceptorError extends Error {\n constructor(message?: string) {\n super(message)\n this.name = 'InterceptorError'\n Object.setPrototypeOf(this, InterceptorError.prototype)\n }\n}\n","import { invariant } from 'outvariant'\nimport { InterceptorError } from './interceptor-error'\nimport { formatResponse, type Logger } from './utils/logger'\n\nexport interface RequestControllerSource {\n passthrough(): void | Promise<void>\n respondWith(response: Response): void | Promise<void>\n errorWith(reason?: unknown): void | Promise<void>\n}\n\ninterface RequestControllerOptions {\n logger: Logger\n requestId: string\n}\n\nexport class RequestController {\n static PENDING = 0 as const\n static PASSTHROUGH = 1 as const\n static RESPONSE = 2 as const\n static ERROR = 3 as const\n\n public readyState: number\n\n /**\n * A Promise that resolves when this controller handles a request.\n * See `controller.readyState` for more information on the handling result.\n */\n public handled: Promise<void>\n\n readonly #handled: PromiseWithResolvers<void>\n\n constructor(\n protected readonly request: Request,\n protected readonly source: RequestControllerSource,\n protected readonly options?: RequestControllerOptions\n ) {\n this.readyState = RequestController.PENDING\n this.#handled = Promise.withResolvers<void>()\n this.handled = this.#handled.promise\n }\n\n /**\n * Perform this request as-is.\n */\n public async passthrough(): Promise<void> {\n invariant.as(\n InterceptorError,\n this.readyState === RequestController.PENDING,\n 'Failed to passthrough the \"%s %s\" request: the request has already been handled',\n this.request.method,\n this.request.url\n )\n\n this.readyState = RequestController.PASSTHROUGH\n if (this.options) {\n this.options.logger.info('[%s] passthrough', this.options.requestId)\n }\n await this.source.passthrough()\n this.#handled.resolve()\n }\n\n /**\n * Respond to this request with the given `Response` instance.\n *\n * @example\n * controller.respondWith(new Response())\n * controller.respondWith(Response.json({ id }))\n * controller.respondWith(Response.error())\n */\n public respondWith(response: Response): void {\n invariant.as(\n InterceptorError,\n this.readyState === RequestController.PENDING,\n 'Failed to respond to the \"%s %s\" request with \"%d %s\": the request has already been handled (%d)',\n this.request.method,\n this.request.url,\n response.status,\n response.statusText || 'OK',\n this.readyState\n )\n\n this.readyState = RequestController.RESPONSE\n if (this.options?.logger.isEnabled('default')) {\n const { logger, requestId } = this.options\n\n void formatResponse(response).then((message) => {\n logger.info('[%s] mocked %s', requestId, message)\n })\n }\n this.#handled.resolve()\n\n /**\n * @note Although `source.respondWith()` is potentially asynchronous,\n * do NOT await it for backward-compatibility. Awaiting it will short-circuit\n * the request listener invocation as soon as a listener responds to a request.\n * Ideally, that's what we want, but that's not what we promise the user.\n */\n this.source.respondWith(response)\n }\n\n /**\n * Error this request with the given reason.\n *\n * @example\n * controller.errorWith()\n * controller.errorWith(new Error('Oops!'))\n * controller.errorWith({ message: 'Oops!'})\n */\n public errorWith(reason?: unknown): void {\n invariant.as(\n InterceptorError,\n this.readyState === RequestController.PENDING,\n 'Failed to error the \"%s %s\" request with \"%s\": the request has already been handled (%d)',\n this.request.method,\n this.request.url,\n reason?.toString(),\n this.readyState\n )\n\n this.readyState = RequestController.ERROR\n if (this.options) {\n this.options.logger.info(\n '[%s] error %o',\n this.options.requestId,\n reason\n )\n }\n this.source.errorWith(reason)\n this.#handled.resolve()\n }\n}\n","import { FetchRequest, FetchResponse } from '../../../utils/fetch-utils'\n\ntype HeaderTuple = [string, string]\ntype RawHeaders = Array<HeaderTuple>\ntype SetHeaderBehavior = 'set' | 'append'\n\nconst kRawHeaders = Symbol('kRawHeaders')\nconst kRestorePatches = Symbol('kRestorePatches')\n\nfunction recordRawHeader(\n headers: Headers,\n args: HeaderTuple,\n behavior: SetHeaderBehavior\n) {\n ensureRawHeadersSymbol(headers, [])\n const rawHeaders = Reflect.get(headers, kRawHeaders) as RawHeaders\n\n if (behavior === 'set') {\n // When recording a set header, ensure we remove any matching existing headers.\n for (let index = rawHeaders.length - 1; index >= 0; index--) {\n if (rawHeaders[index][0].toLowerCase() === args[0].toLowerCase()) {\n rawHeaders.splice(index, 1)\n }\n }\n }\n\n rawHeaders.push(args)\n}\n\n/**\n * Define the raw headers symbol on the given `Headers` instance.\n * If the symbol already exists, this function does nothing.\n */\nfunction ensureRawHeadersSymbol(\n headers: Headers,\n rawHeaders: RawHeaders\n): void {\n if (Reflect.has(headers, kRawHeaders)) {\n return\n }\n\n defineRawHeadersSymbol(headers, rawHeaders)\n}\n\n/**\n * Define the raw headers symbol on the given `Headers` instance.\n * If the symbol already exists, it gets overridden.\n */\nfunction defineRawHeadersSymbol(headers: Headers, rawHeaders: RawHeaders) {\n Object.defineProperty(headers, kRawHeaders, {\n value: rawHeaders,\n enumerable: false,\n // Mark the symbol as configurable so its value can be overridden.\n // Overrides happen when merging raw headers from multiple sources.\n // E.g. new Request(new Request(url, { headers }), { headers })\n configurable: true,\n })\n}\n\n/**\n * Patch the global `Headers` class to store raw headers.\n * This is for compatibility with `IncomingMessage.prototype.rawHeaders`.\n *\n * @note Node.js has their own raw headers symbol but it\n * only records the first header name in case of multi-value headers.\n * Any other headers are normalized before comparing. This makes it\n * incompatible with the `rawHeaders` format.\n *\n * let h = new Headers()\n * h.append('X-Custom', 'one')\n * h.append('x-custom', 'two')\n * h[Symbol('headers map')] // Map { 'X-Custom' => 'one, two' }\n */\nexport function recordRawFetchHeaders(): () => void {\n // Prevent patching the Headers prototype multiple times.\n if (Reflect.get(Headers, kRestorePatches)) {\n return Reflect.get(Headers, kRestorePatches)\n }\n\n const {\n Headers: OriginalHeaders,\n Request: OriginalRequest,\n Response: OriginalResponse,\n } = globalThis\n const { set, append, delete: headersDeleteMethod } = Headers.prototype\n\n Object.defineProperty(Headers, kRestorePatches, {\n value: () => {\n Headers.prototype.set = set\n Headers.prototype.append = append\n Headers.prototype.delete = headersDeleteMethod\n globalThis.Headers = OriginalHeaders\n\n globalThis.Request = OriginalRequest\n globalThis.Response = OriginalResponse\n\n Object.setPrototypeOf(FetchRequest, OriginalRequest)\n Object.setPrototypeOf(FetchRequest.prototype, OriginalRequest.prototype)\n Object.setPrototypeOf(FetchResponse, OriginalResponse)\n Object.setPrototypeOf(FetchResponse.prototype, OriginalResponse.prototype)\n\n Reflect.deleteProperty(Headers, kRestorePatches)\n },\n enumerable: false,\n /**\n * @note Mark this property as configurable\n * so we can delete it using `Reflect.delete` during cleanup.\n */\n configurable: true,\n })\n\n Object.defineProperty(globalThis, 'Headers', {\n enumerable: true,\n writable: true,\n value: new Proxy(Headers, {\n construct(target, args, newTarget) {\n const headersInit = args[0] || []\n\n if (\n headersInit instanceof Headers &&\n Reflect.has(headersInit, kRawHeaders)\n ) {\n // Ensure each header tuple has exactly 2 elements (name, value).\n // Node.js 24+ may have stored tuples with extra internal arguments.\n const rawHeadersFromInit = Reflect.get(\n headersInit,\n kRawHeaders\n ) as RawHeaders\n const sanitizedHeaders = rawHeadersFromInit.map(\n (tuple): HeaderTuple => [tuple[0], tuple[1]]\n )\n const headers = Reflect.construct(\n target,\n [sanitizedHeaders],\n newTarget\n )\n ensureRawHeadersSymbol(headers, [\n /**\n * @note Spread the retrieved headers to clone them.\n * This prevents multiple Headers instances from pointing\n * at the same internal \"rawHeaders\" array.\n */\n ...sanitizedHeaders,\n ])\n return headers\n }\n\n const headers = Reflect.construct(target, args, newTarget)\n\n // Request/Response constructors will set the symbol\n // upon creating a new instance, using the raw developer\n // input as the raw headers. Skip the symbol altogether\n // in those cases because the input to Headers will be normalized.\n if (!Reflect.has(headers, kRawHeaders)) {\n const rawHeadersInit = Array.isArray(headersInit)\n ? headersInit\n : Object.entries(headersInit)\n ensureRawHeadersSymbol(headers, rawHeadersInit)\n }\n\n return headers\n },\n }),\n })\n\n Headers.prototype.set = new Proxy(Headers.prototype.set, {\n apply(target, thisArg, args: HeaderTuple) {\n // Use only the first two arguments (name, value) to record raw headers.\n // Node.js 24+ may pass additional internal arguments that should not\n // be included in the raw headers array.\n recordRawHeader(thisArg, [args[0], args[1]], 'set')\n return Reflect.apply(target, thisArg, args)\n },\n })\n\n Headers.prototype.append = new Proxy(Headers.prototype.append, {\n apply(target, thisArg, args: HeaderTuple) {\n // Use only the first two arguments (name, value) to record raw headers.\n // Node.js 24+ may pass additional internal arguments that should not\n // be included in the raw headers array.\n recordRawHeader(thisArg, [args[0], args[1]], 'append')\n return Reflect.apply(target, thisArg, args)\n },\n })\n\n Headers.prototype.delete = new Proxy(Headers.prototype.delete, {\n apply(target, thisArg, args: [string]) {\n const rawHeaders = Reflect.get(thisArg, kRawHeaders) as RawHeaders\n\n if (rawHeaders) {\n for (let index = rawHeaders.length - 1; index >= 0; index--) {\n if (rawHeaders[index][0].toLowerCase() === args[0].toLowerCase()) {\n rawHeaders.splice(index, 1)\n }\n }\n }\n\n return Reflect.apply(target, thisArg, args)\n },\n })\n\n Object.defineProperty(globalThis, 'Request', {\n enumerable: true,\n writable: true,\n value: new Proxy(Request, {\n construct(target, args, newTarget) {\n const request = Reflect.construct(target, args, newTarget)\n const inferredRawHeaders: RawHeaders = []\n\n // Infer raw headers from a `Request` instance used as init.\n if (typeof args[0] === 'object' && args[0].headers != null) {\n inferredRawHeaders.push(...inferRawHeaders(args[0].headers))\n }\n\n // Infer raw headers from the \"headers\" init argument.\n if (typeof args[1] === 'object' && args[1].headers != null) {\n inferredRawHeaders.push(...inferRawHeaders(args[1].headers))\n }\n\n if (inferredRawHeaders.length > 0) {\n ensureRawHeadersSymbol(request.headers, inferredRawHeaders)\n }\n\n return request\n },\n }),\n })\n\n Object.defineProperty(globalThis, 'Response', {\n enumerable: true,\n writable: true,\n value: new Proxy(Response, {\n construct(target, args, newTarget) {\n const response = Reflect.construct(target, args, newTarget)\n\n if (typeof args[1] === 'object' && args[1].headers != null) {\n ensureRawHeadersSymbol(\n response.headers,\n inferRawHeaders(args[1].headers)\n )\n }\n\n return response\n },\n }),\n })\n\n /**\n * Re-parent FetchRequest/FetchResponse so their `super()` calls go\n * through the proxied globalThis.Request/Response above. Without this,\n * FetchRequest extends the statically-captured (original) Request,\n * bypassing the construct proxy that records raw headers.\n */\n Object.setPrototypeOf(FetchRequest, globalThis.Request)\n Object.setPrototypeOf(FetchRequest.prototype, globalThis.Request.prototype)\n Object.setPrototypeOf(FetchResponse, globalThis.Response)\n Object.setPrototypeOf(FetchResponse.prototype, globalThis.Response.prototype)\n\n return restoreHeadersPrototype\n}\n\nexport function restoreHeadersPrototype() {\n if (!Reflect.get(Headers, kRestorePatches)) {\n return\n }\n\n Reflect.get(Headers, kRestorePatches)()\n}\n\nexport function getRawFetchHeaders(headers: Headers): RawHeaders {\n // If the raw headers recording failed for some reason,\n // use the normalized header entries instead.\n if (!Reflect.has(headers, kRawHeaders)) {\n return Array.from(headers.entries())\n }\n\n const rawHeaders = Reflect.get(headers, kRawHeaders) as RawHeaders\n return rawHeaders.length > 0 ? rawHeaders : Array.from(headers.entries())\n}\n\n/**\n * Infers the raw headers from the given `HeadersInit` provided\n * to the Request/Response constructor.\n *\n * If the `init.headers` is a Headers instance, use it directly.\n * That means the headers were created standalone and already have\n * the raw headers stored.\n * If the `init.headers` is a HeadersInit, create a new Headers\n * instance out of it.\n */\nfunction inferRawHeaders(headers: HeadersInit): RawHeaders {\n if (headers instanceof Headers) {\n return Reflect.get(headers, kRawHeaders) || []\n }\n\n return Reflect.get(new Headers(headers), kRawHeaders)\n}\n\nexport function copyRawHeaders(source: Headers, destination: Headers): void {\n const rawHeaders = [...getRawFetchHeaders(source)]\n\n if (rawHeaders.length === 0) {\n return\n }\n\n /**\n * @note Add headers from trhe destination that raw headers from the source\n * don't have. Undici automatically appends a \"Content-Type\" header for responses\n * and, for some reason, that change is not recorded. This preserves it.\n */\n for (const [name, value] of destination) {\n if (\n rawHeaders.every(\n (header) => header[0].toLowerCase() !== name.toLowerCase()\n )\n ) {\n rawHeaders.push([name, value])\n }\n }\n\n defineRawHeadersSymbol(destination, rawHeaders)\n}\n","/**\n * Returns the value behind the symbol with the given name.\n */\nexport function getValueBySymbol<T>(\n symbolName: string,\n source: object\n): T | undefined {\n const ownSymbols = Object.getOwnPropertySymbols(source)\n\n const symbol = ownSymbols.find((symbol) => {\n return symbol.description === symbolName\n })\n\n if (symbol) {\n return Reflect.get(source, symbol)\n }\n\n return\n}\n","/**\n * Determines if a given value is an instance of object.\n */\nexport function isObject<T>(value: any, loose = false): value is T {\n return loose\n ? Object.prototype.toString.call(value).startsWith('[object ')\n : Object.prototype.toString.call(value) === '[object Object]'\n}\n","/**\n * A function that validates if property access is possible on an object\n * without throwing. It returns `true` if the property access is possible\n * and `false` otherwise.\n *\n * Environments like miniflare will throw on property access on certain objects\n * like Request and Response, for unimplemented properties.\n */\nexport function isPropertyAccessible<Obj extends Record<string, any>>(\n obj: Obj,\n key: keyof Obj\n) {\n try {\n obj[key]\n return true\n } catch {\n return false\n }\n}\n","import { isObject } from './is-object'\nimport { isPropertyAccessible } from './is-property-accessible'\n\n/**\n * Creates a generic 500 Unhandled Exception response.\n */\nexport function createServerErrorResponse(body: unknown): Response {\n return new Response(\n JSON.stringify(\n body instanceof Error\n ? {\n name: body.name,\n message: body.message,\n stack: body.stack,\n }\n : body\n ),\n {\n status: 500,\n statusText: 'Unhandled Exception',\n headers: {\n 'Content-Type': 'application/json',\n },\n }\n )\n}\n\nexport type ResponseError = Response & { type: 'error' }\n\n/**\n * A key on the error a mocked `Response.error()` destroys the socket\n * with, referencing that error response. Allows the client-side\n * interceptors (e.g. fetch) to surface the error response to the\n * consumer instead of the internal socket error.\n */\nexport const kErrorResponse = Symbol('kErrorResponse')\n\n/**\n * Get the mocked error response that caused the given error, if any.\n */\nexport function getErrorResponse(error: unknown): ResponseError | undefined {\n if (\n error instanceof Error &&\n kErrorResponse in error &&\n isResponseError(error[kErrorResponse])\n ) {\n return error[kErrorResponse]\n }\n\n return undefined\n}\n\n/**\n * Check if the given response is a `Response.error()`.\n *\n * @note Some environments, like Miniflare (Cloudflare) do not\n * implement the \"Response.type\" property and throw on its access.\n * Safely check if we can access \"type\" on \"Response\" before continuing.\n * @see https://github.com/mswjs/msw/issues/1834\n */\nexport function isResponseError(response: unknown): response is ResponseError {\n return (\n response != null &&\n response instanceof Response &&\n isPropertyAccessible(response, 'type') &&\n response.type === 'error'\n )\n}\n\n/**\n * Check if the given value is a `Response` or a Response-like object.\n * This is different from `value instanceof Response` because it supports\n * custom `Response` constructors, like the one when using Undici directly.\n */\nexport function isResponseLike(value: unknown): value is Response {\n return (\n isObject<Record<string, any>>(value, true) &&\n isPropertyAccessible(value, 'status') &&\n isPropertyAccessible(value, 'statusText') &&\n isPropertyAccessible(value, 'bodyUsed')\n )\n}\n","import { copyRawHeaders } from '../interceptors/ClientRequest/utils/record-raw-headers'\nimport { getValueBySymbol } from './get-value-by-symbol'\nimport { isResponseError } from './response-utils'\n\ninterface UndiciRequestState extends RequestInit {}\n\ninterface FetchRequestInit extends Omit<RequestInit, 'mode'> {\n mode?: RequestMode | 'websocket' | 'webtransport'\n duplex?: 'half' | 'full'\n}\n\nexport class FetchRequest extends Request {\n static #resolveProperty<T extends keyof FetchRequestInit & keyof Request>(\n input: RequestInfo | URL,\n init: FetchRequestInit = {},\n key: T\n ): FetchRequestInit[T] {\n return init[key] ?? (input instanceof Request ? input[key] : undefined)\n }\n\n /**\n * Check if the given request method is configurable.\n * @see https://fetch.spec.whatwg.org/#methods\n */\n static isConfigurableMethod(method: string): boolean {\n return method !== 'CONNECT' && method !== 'TRACE' && method !== 'TRACK'\n }\n\n static isMethodWithBody(method: string): boolean {\n return (\n method !== 'HEAD' &&\n method !== 'GET' &&\n FetchRequest.isConfigurableMethod(method)\n )\n }\n\n /**\n * Check if the given request `mode` is configurable.\n * @see https://fetch.spec.whatwg.org/#concept-request-mode\n */\n static isConfigurableMode(mode: string): boolean {\n return (\n mode !== 'navigate' && mode !== 'websocket' && mode !== 'webtransport'\n )\n }\n\n constructor(input: URL | RequestInfo, init?: FetchRequestInit) {\n const method = FetchRequest.#resolveProperty(input, init, 'method') || 'GET'\n const safeMethod = FetchRequest.isConfigurableMethod(method)\n ? method\n : 'GET'\n\n const hasExplicitBody = init != null && 'body' in init\n\n /**\n * Only include `body` in the super init when it needs to be overridden.\n * When `input` is a Request and no explicit body is in `init`, let the\n * Request constructor handle body transfer naturally so it properly\n * marks the original request's body as consumed (bodyUsed = true).\n */\n const bodyInit: { body?: BodyInit | null } = !FetchRequest.isMethodWithBody(\n method\n )\n ? { body: undefined }\n : hasExplicitBody\n ? { body: init.body }\n : {}\n\n const mode =\n (FetchRequest.#resolveProperty(input, init, 'mode') as RequestMode) ??\n undefined\n const safeMode = FetchRequest.isConfigurableMode(mode) ? mode : undefined\n\n super(input, {\n ...(init || {}),\n method: safeMethod,\n mode: safeMode,\n // @ts-expect-error Untyped Node.js property.\n duplex:\n init?.duplex ??\n (FetchRequest.isMethodWithBody(method) ? 'half' : undefined),\n ...bodyInit,\n })\n\n if (method !== safeMethod) {\n this.#setInternalProperty('method', method)\n }\n\n if (method === 'CONNECT') {\n const url = new URL(input instanceof Request ? input.url : input)\n\n let authority: string\n\n /**\n * @note Node.js has a bug parsing raw CONNECT requests URLs like\n * \"http://127.0.0.1:1337/localhost:80\". It would treat \"localhost:\" as a protocol.\n */\n if (url.protocol === 'localhost:') {\n authority = url.href\n } else {\n authority = url.pathname.replace(/^\\/+/, '')\n }\n\n /**\n * @note Define \"url\" as a getter because Undici uses their own\n * logic to resolve the \"request.url\" property. Simply reassigning\n * its value doesn't do anything. This is a destructive action\n * but it's safe because \"CONNECT\" requests are forbidden per fetch.\n */\n Object.defineProperty(this, 'url', {\n get: () => authority,\n enumerable: true,\n configurable: true,\n })\n }\n\n if (mode != null && mode !== safeMode) {\n this.#setInternalProperty('mode', mode)\n }\n }\n\n #setInternalProperty<T extends keyof Request>(\n key: T,\n value: Request[T]\n ): void {\n const internalState = getValueBySymbol<UndiciRequestState>('state', this)\n\n if (internalState) {\n Reflect.set(internalState, key, value)\n } else {\n Object.defineProperty(this, key, {\n value,\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n }\n}\n\nexport interface FetchResponseInit extends ResponseInit {\n url?: string\n}\n\ninterface UndiciResponseState {\n aborted: boolean\n rangeRequested: boolean\n timingAllowPassed: boolean\n requestIncludesCredentials: boolean\n type: ResponseType\n status: number\n statusText: string\n timingInfo: unknown\n cacheState: unknown\n headersList: Record<symbol, Map<string, unknown>>\n urlList: Array<URL>\n body?: {\n stream: ReadableStream\n source: unknown\n length: number\n }\n}\n\nconst kStatus = Symbol('kStatus')\nconst kUrl = Symbol('kUrl')\n\nexport class FetchResponse extends Response {\n static from(response: Response, init?: FetchResponseInit): FetchResponse {\n if (response instanceof FetchResponse) {\n return response\n }\n\n if (isResponseError(response)) {\n return response\n }\n\n const fetchResponse = new FetchResponse(response.body, {\n url: init?.url ?? response.url,\n status: init?.status || response.status,\n statusText: init?.statusText ?? response.statusText,\n headers: init?.headers ?? response.headers,\n })\n\n copyRawHeaders(response.headers, fetchResponse.headers)\n\n return fetchResponse\n }\n\n /**\n * Response status codes for responses that cannot have body.\n * @see https://fetch.spec.whatwg.org/#statuses\n */\n static readonly STATUS_CODES_WITHOUT_BODY = [101, 103, 204, 205, 304]\n\n static readonly STATUS_CODES_WITH_REDIRECT = [301, 302, 303, 307, 308]\n\n static isConfigurableStatusCode(status: number): boolean {\n return status >= 200 && status <= 599\n }\n\n static isRedirectResponse(status: number): boolean {\n return FetchResponse.STATUS_CODES_WITH_REDIRECT.includes(status)\n }\n\n /**\n * Returns a boolean indicating whether the given response status\n * code represents a response that can have a body.\n */\n static isResponseWithBody(status: number): boolean {\n return !FetchResponse.STATUS_CODES_WITHOUT_BODY.includes(status)\n }\n\n static setStatus(status: number, response: Response): void {\n /**\n * @note Undici keeps an internal \"Symbol(state)\" that holds\n * the actual value of response status. Update that in Node.js.\n */\n const internalState = getValueBySymbol<UndiciResponseState>(\n 'state',\n response\n )\n\n if (internalState) {\n internalState.status = status\n } else {\n Object.defineProperty(response, 'status', {\n value: status,\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n\n Object.defineProperty(response, kStatus, {\n value: status,\n enumerable: false,\n })\n }\n\n static setUrl(url: string | undefined, response: Response): void {\n if (!url || url === 'about:' || !URL.canParse(url)) {\n return\n }\n\n const state = getValueBySymbol<UndiciResponseState>('state', response)\n\n if (state) {\n // In Undici, push the URL to the internal list of URLs.\n // This will respect the `response.url` getter logic correctly.\n state.urlList.push(new URL(url))\n } else {\n // In other libraries, redefine the `url` property directly.\n Object.defineProperty(response, 'url', {\n value: url,\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n\n Object.defineProperty(response, kUrl, {\n value: url,\n enumerable: false,\n })\n }\n\n /**\n * Parses the given raw HTTP headers into a Fetch API `Headers` instance.\n */\n static parseRawHeaders(rawHeaders: Array<string>): Headers {\n const headers = new Headers()\n\n for (let line = 0; line < rawHeaders.length; line += 2) {\n headers.append(rawHeaders[line], rawHeaders[line + 1])\n }\n\n return headers\n }\n\n /**\n * Safely clones the given `Response`.\n * Coerces response clone exceptions into 500 mocked responses.\n * Handy in the environments that introduce arbitrary response\n * cloning restrictions, like \"101 Switching Protocols\" cloning\n * in \"miniflare\".\n */\n static clone(response: Response): Response {\n try {\n const clone = response.clone()\n return clone\n } catch (error) {\n return Response.json(\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : {},\n {\n status: 500,\n statusText: 'Unclonable Response',\n }\n )\n }\n }\n\n #status?: number\n #url?: string\n\n constructor(body?: BodyInit | null, init: FetchResponseInit = {}) {\n const status = init.status ?? 200\n const safeStatus = FetchResponse.isConfigurableStatusCode(status)\n ? status\n : 200\n const finalBody = FetchResponse.isResponseWithBody(status) ? body : null\n\n super(finalBody, {\n status: safeStatus,\n statusText: init.statusText,\n headers: init.headers,\n })\n\n /**\n * Since Node.js v24, Undici stores the Response state in an inaccessible field \"#state\".\n * Forward the modified status/URL to the cloned response manually.\n * @see https://github.com/nodejs/undici/blob/f734c87280e626c75f59aad55b65eb6a89cef392/lib/web/fetch/response.js#L242\n */\n if (status !== safeStatus) {\n FetchResponse.setStatus(status, this)\n }\n\n FetchResponse.setUrl(init.url, this)\n }\n\n public clone() {\n const clonedResponse = super.clone()\n\n const customStatus = Reflect.get(this, kStatus) as number | undefined\n\n if (customStatus) {\n FetchResponse.setStatus(customStatus, clonedResponse)\n }\n\n const customUrl = Reflect.get(this, kUrl) as string | undefined\n\n if (customUrl) {\n FetchResponse.setUrl(customUrl, clonedResponse)\n }\n\n return clonedResponse\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fetch-utils-D-_xeRlK.js","names":["#handled","#resolveProperty","#setInternalProperty"],"sources":["../../src/interceptor-error.ts","../../src/request-controller.ts","../../src/interceptors/ClientRequest/utils/record-raw-headers.ts","../../src/utils/get-value-by-symbol.ts","../../src/utils/is-object.ts","../../src/utils/is-property-accessible.ts","../../src/utils/response-utils.ts","../../src/utils/fetch-utils.ts"],"sourcesContent":["export class InterceptorError extends Error {\n constructor(message?: string) {\n super(message)\n this.name = 'InterceptorError'\n Object.setPrototypeOf(this, InterceptorError.prototype)\n }\n}\n","import { invariant } from 'outvariant'\nimport { InterceptorError } from './interceptor-error'\nimport { formatResponse, type Logger } from './utils/logger'\n\nexport interface RequestControllerSource {\n passthrough(): void | Promise<void>\n respondWith(response: Response): void | Promise<void>\n errorWith(reason?: unknown): void | Promise<void>\n}\n\ninterface RequestControllerOptions {\n logger: Logger\n requestId: string\n}\n\nexport class RequestController {\n static PENDING = 0 as const\n static PASSTHROUGH = 1 as const\n static RESPONSE = 2 as const\n static ERROR = 3 as const\n\n public readyState: number\n\n /**\n * A Promise that resolves when this controller handles a request.\n * See `controller.readyState` for more information on the handling result.\n */\n public handled: Promise<void>\n\n readonly #handled: PromiseWithResolvers<void>\n\n constructor(\n protected readonly request: Request,\n protected readonly source: RequestControllerSource,\n protected readonly options?: RequestControllerOptions\n ) {\n this.readyState = RequestController.PENDING\n this.#handled = Promise.withResolvers<void>()\n this.handled = this.#handled.promise\n }\n\n /**\n * Perform this request as-is.\n */\n public async passthrough(): Promise<void> {\n invariant.as(\n InterceptorError,\n this.readyState === RequestController.PENDING,\n 'Failed to passthrough the \"%s %s\" request: the request has already been handled',\n this.request.method,\n this.request.url\n )\n\n this.readyState = RequestController.PASSTHROUGH\n if (this.options) {\n this.options.logger.info('[%s] passthrough', this.options.requestId)\n }\n await this.source.passthrough()\n this.#handled.resolve()\n }\n\n /**\n * Respond to this request with the given `Response` instance.\n *\n * @example\n * controller.respondWith(new Response())\n * controller.respondWith(Response.json({ id }))\n * controller.respondWith(Response.error())\n */\n public respondWith(response: Response): void {\n invariant.as(\n InterceptorError,\n this.readyState === RequestController.PENDING,\n 'Failed to respond to the \"%s %s\" request with \"%d %s\": the request has already been handled (%d)',\n this.request.method,\n this.request.url,\n response.status,\n response.statusText || 'OK',\n this.readyState\n )\n\n this.readyState = RequestController.RESPONSE\n if (this.options?.logger.isEnabled('default')) {\n const { logger, requestId } = this.options\n\n void formatResponse(response).then((message) => {\n logger.info('[%s] mocked %s', requestId, message)\n })\n }\n this.#handled.resolve()\n\n /**\n * @note Although `source.respondWith()` is potentially asynchronous,\n * do NOT await it for backward-compatibility. Awaiting it will short-circuit\n * the request listener invocation as soon as a listener responds to a request.\n * Ideally, that's what we want, but that's not what we promise the user.\n */\n this.source.respondWith(response)\n }\n\n /**\n * Error this request with the given reason.\n *\n * @example\n * controller.errorWith()\n * controller.errorWith(new Error('Oops!'))\n * controller.errorWith({ message: 'Oops!'})\n */\n public errorWith(reason?: unknown): void {\n invariant.as(\n InterceptorError,\n this.readyState === RequestController.PENDING,\n 'Failed to error the \"%s %s\" request with \"%s\": the request has already been handled (%d)',\n this.request.method,\n this.request.url,\n reason?.toString(),\n this.readyState\n )\n\n this.readyState = RequestController.ERROR\n if (this.options) {\n this.options.logger.info(\n '[%s] error %o',\n this.options.requestId,\n reason\n )\n }\n this.source.errorWith(reason)\n this.#handled.resolve()\n }\n}\n","import { FetchRequest, FetchResponse } from '../../../utils/fetch-utils'\n\ntype HeaderTuple = [string, string]\ntype RawHeaders = Array<HeaderTuple>\ntype SetHeaderBehavior = 'set' | 'append'\n\nconst kRawHeaders = Symbol('kRawHeaders')\nconst kRestorePatches = Symbol('kRestorePatches')\n\nfunction recordRawHeader(\n headers: Headers,\n args: HeaderTuple,\n behavior: SetHeaderBehavior\n) {\n ensureRawHeadersSymbol(headers, [])\n const rawHeaders = Reflect.get(headers, kRawHeaders) as RawHeaders\n\n if (behavior === 'set') {\n // When recording a set header, ensure we remove any matching existing headers.\n for (let index = rawHeaders.length - 1; index >= 0; index--) {\n if (rawHeaders[index][0].toLowerCase() === args[0].toLowerCase()) {\n rawHeaders.splice(index, 1)\n }\n }\n }\n\n rawHeaders.push(args)\n}\n\n/**\n * Define the raw headers symbol on the given `Headers` instance.\n * If the symbol already exists, this function does nothing.\n */\nfunction ensureRawHeadersSymbol(\n headers: Headers,\n rawHeaders: RawHeaders\n): void {\n if (Reflect.has(headers, kRawHeaders)) {\n return\n }\n\n defineRawHeadersSymbol(headers, rawHeaders)\n}\n\n/**\n * Define the raw headers symbol on the given `Headers` instance.\n * If the symbol already exists, it gets overridden.\n */\nfunction defineRawHeadersSymbol(headers: Headers, rawHeaders: RawHeaders) {\n Object.defineProperty(headers, kRawHeaders, {\n value: rawHeaders,\n enumerable: false,\n // Mark the symbol as configurable so its value can be overridden.\n // Overrides happen when merging raw headers from multiple sources.\n // E.g. new Request(new Request(url, { headers }), { headers })\n configurable: true,\n })\n}\n\n/**\n * Patch the global `Headers` class to store raw headers.\n * This is for compatibility with `IncomingMessage.prototype.rawHeaders`.\n *\n * @note Node.js has their own raw headers symbol but it\n * only records the first header name in case of multi-value headers.\n * Any other headers are normalized before comparing. This makes it\n * incompatible with the `rawHeaders` format.\n *\n * let h = new Headers()\n * h.append('X-Custom', 'one')\n * h.append('x-custom', 'two')\n * h[Symbol('headers map')] // Map { 'X-Custom' => 'one, two' }\n */\nexport function recordRawFetchHeaders(): () => void {\n // Prevent patching the Headers prototype multiple times.\n if (Reflect.get(Headers, kRestorePatches)) {\n return Reflect.get(Headers, kRestorePatches)\n }\n\n const {\n Headers: OriginalHeaders,\n Request: OriginalRequest,\n Response: OriginalResponse,\n } = globalThis\n const { set, append, delete: headersDeleteMethod } = Headers.prototype\n\n Object.defineProperty(Headers, kRestorePatches, {\n value: () => {\n Headers.prototype.set = set\n Headers.prototype.append = append\n Headers.prototype.delete = headersDeleteMethod\n globalThis.Headers = OriginalHeaders\n\n globalThis.Request = OriginalRequest\n globalThis.Response = OriginalResponse\n\n Object.setPrototypeOf(FetchRequest, OriginalRequest)\n Object.setPrototypeOf(FetchRequest.prototype, OriginalRequest.prototype)\n Object.setPrototypeOf(FetchResponse, OriginalResponse)\n Object.setPrototypeOf(FetchResponse.prototype, OriginalResponse.prototype)\n\n Reflect.deleteProperty(Headers, kRestorePatches)\n },\n enumerable: false,\n /**\n * @note Mark this property as configurable\n * so we can delete it using `Reflect.delete` during cleanup.\n */\n configurable: true,\n })\n\n Object.defineProperty(globalThis, 'Headers', {\n enumerable: true,\n writable: true,\n value: new Proxy(Headers, {\n construct(target, args, newTarget) {\n const headersInit = args[0] || []\n\n if (\n headersInit instanceof Headers &&\n Reflect.has(headersInit, kRawHeaders)\n ) {\n // Ensure each header tuple has exactly 2 elements (name, value).\n // Node.js 24+ may have stored tuples with extra internal arguments.\n const rawHeadersFromInit = Reflect.get(\n headersInit,\n kRawHeaders\n ) as RawHeaders\n const sanitizedHeaders = rawHeadersFromInit.map(\n (tuple): HeaderTuple => [tuple[0], tuple[1]]\n )\n const headers = Reflect.construct(\n target,\n [sanitizedHeaders],\n newTarget\n )\n ensureRawHeadersSymbol(headers, [\n /**\n * @note Spread the retrieved headers to clone them.\n * This prevents multiple Headers instances from pointing\n * at the same internal \"rawHeaders\" array.\n */\n ...sanitizedHeaders,\n ])\n return headers\n }\n\n const headers = Reflect.construct(target, args, newTarget)\n\n // Request/Response constructors will set the symbol\n // upon creating a new instance, using the raw developer\n // input as the raw headers. Skip the symbol altogether\n // in those cases because the input to Headers will be normalized.\n if (!Reflect.has(headers, kRawHeaders)) {\n const rawHeadersInit = Array.isArray(headersInit)\n ? headersInit\n : Object.entries(headersInit)\n ensureRawHeadersSymbol(headers, rawHeadersInit)\n }\n\n return headers\n },\n }),\n })\n\n Headers.prototype.set = new Proxy(Headers.prototype.set, {\n apply(target, thisArg, args: HeaderTuple) {\n // Use only the first two arguments (name, value) to record raw headers.\n // Node.js 24+ may pass additional internal arguments that should not\n // be included in the raw headers array.\n recordRawHeader(thisArg, [args[0], args[1]], 'set')\n return Reflect.apply(target, thisArg, args)\n },\n })\n\n Headers.prototype.append = new Proxy(Headers.prototype.append, {\n apply(target, thisArg, args: HeaderTuple) {\n // Use only the first two arguments (name, value) to record raw headers.\n // Node.js 24+ may pass additional internal arguments that should not\n // be included in the raw headers array.\n recordRawHeader(thisArg, [args[0], args[1]], 'append')\n return Reflect.apply(target, thisArg, args)\n },\n })\n\n Headers.prototype.delete = new Proxy(Headers.prototype.delete, {\n apply(target, thisArg, args: [string]) {\n const rawHeaders = Reflect.get(thisArg, kRawHeaders) as RawHeaders\n\n if (rawHeaders) {\n for (let index = rawHeaders.length - 1; index >= 0; index--) {\n if (rawHeaders[index][0].toLowerCase() === args[0].toLowerCase()) {\n rawHeaders.splice(index, 1)\n }\n }\n }\n\n return Reflect.apply(target, thisArg, args)\n },\n })\n\n Object.defineProperty(globalThis, 'Request', {\n enumerable: true,\n writable: true,\n value: new Proxy(Request, {\n construct(target, args, newTarget) {\n const request = Reflect.construct(target, args, newTarget)\n const inferredRawHeaders: RawHeaders = []\n\n // Infer raw headers from a `Request` instance used as init.\n if (typeof args[0] === 'object' && args[0].headers != null) {\n inferredRawHeaders.push(...inferRawHeaders(args[0].headers))\n }\n\n // Infer raw headers from the \"headers\" init argument.\n if (typeof args[1] === 'object' && args[1].headers != null) {\n inferredRawHeaders.push(...inferRawHeaders(args[1].headers))\n }\n\n if (inferredRawHeaders.length > 0) {\n ensureRawHeadersSymbol(request.headers, inferredRawHeaders)\n }\n\n return request\n },\n }),\n })\n\n Object.defineProperty(globalThis, 'Response', {\n enumerable: true,\n writable: true,\n value: new Proxy(Response, {\n construct(target, args, newTarget) {\n const response = Reflect.construct(target, args, newTarget)\n\n if (typeof args[1] === 'object' && args[1].headers != null) {\n ensureRawHeadersSymbol(\n response.headers,\n inferRawHeaders(args[1].headers)\n )\n }\n\n return response\n },\n }),\n })\n\n /**\n * Re-parent FetchRequest/FetchResponse so their `super()` calls go\n * through the proxied globalThis.Request/Response above. Without this,\n * FetchRequest extends the statically-captured (original) Request,\n * bypassing the construct proxy that records raw headers.\n */\n Object.setPrototypeOf(FetchRequest, globalThis.Request)\n Object.setPrototypeOf(FetchRequest.prototype, globalThis.Request.prototype)\n Object.setPrototypeOf(FetchResponse, globalThis.Response)\n Object.setPrototypeOf(FetchResponse.prototype, globalThis.Response.prototype)\n\n return restoreHeadersPrototype\n}\n\nexport function restoreHeadersPrototype() {\n if (!Reflect.get(Headers, kRestorePatches)) {\n return\n }\n\n Reflect.get(Headers, kRestorePatches)()\n}\n\nexport function getRawFetchHeaders(headers: Headers): RawHeaders {\n // If the raw headers recording failed for some reason,\n // use the normalized header entries instead.\n if (!Reflect.has(headers, kRawHeaders)) {\n return Array.from(headers.entries())\n }\n\n const rawHeaders = Reflect.get(headers, kRawHeaders) as RawHeaders\n return rawHeaders.length > 0 ? rawHeaders : Array.from(headers.entries())\n}\n\n/**\n * Infers the raw headers from the given `HeadersInit` provided\n * to the Request/Response constructor.\n *\n * If the `init.headers` is a Headers instance, use it directly.\n * That means the headers were created standalone and already have\n * the raw headers stored.\n * If the `init.headers` is a HeadersInit, create a new Headers\n * instance out of it.\n */\nfunction inferRawHeaders(headers: HeadersInit): RawHeaders {\n if (headers instanceof Headers) {\n return Reflect.get(headers, kRawHeaders) || []\n }\n\n return Reflect.get(new Headers(headers), kRawHeaders)\n}\n\nexport function copyRawHeaders(source: Headers, destination: Headers): void {\n const rawHeaders = [...getRawFetchHeaders(source)]\n\n if (rawHeaders.length === 0) {\n return\n }\n\n /**\n * @note Add headers from trhe destination that raw headers from the source\n * don't have. Undici automatically appends a \"Content-Type\" header for responses\n * and, for some reason, that change is not recorded. This preserves it.\n */\n for (const [name, value] of destination) {\n if (\n rawHeaders.every(\n (header) => header[0].toLowerCase() !== name.toLowerCase()\n )\n ) {\n rawHeaders.push([name, value])\n }\n }\n\n defineRawHeadersSymbol(destination, rawHeaders)\n}\n","/**\n * Returns the value behind the symbol with the given name.\n */\nexport function getValueBySymbol<T>(\n symbolName: string,\n source: object\n): T | undefined {\n const ownSymbols = Object.getOwnPropertySymbols(source)\n\n const symbol = ownSymbols.find((symbol) => {\n return symbol.description === symbolName\n })\n\n if (symbol) {\n return Reflect.get(source, symbol)\n }\n\n return\n}\n","/**\n * Determines if a given value is an instance of object.\n */\nexport function isObject<T>(value: any, loose = false): value is T {\n return loose\n ? Object.prototype.toString.call(value).startsWith('[object ')\n : Object.prototype.toString.call(value) === '[object Object]'\n}\n","/**\n * A function that validates if property access is possible on an object\n * without throwing. It returns `true` if the property access is possible\n * and `false` otherwise.\n *\n * Environments like miniflare will throw on property access on certain objects\n * like Request and Response, for unimplemented properties.\n */\nexport function isPropertyAccessible<Obj extends Record<string, any>>(\n obj: Obj,\n key: keyof Obj\n) {\n try {\n obj[key]\n return true\n } catch {\n return false\n }\n}\n","import { isObject } from './is-object'\nimport { isPropertyAccessible } from './is-property-accessible'\n\n/**\n * Creates a generic 500 Unhandled Exception response.\n */\nexport function createServerErrorResponse(body: unknown): Response {\n return new Response(\n JSON.stringify(\n body instanceof Error\n ? {\n name: body.name,\n message: body.message,\n stack: body.stack,\n }\n : body\n ),\n {\n status: 500,\n statusText: 'Unhandled Exception',\n headers: {\n 'Content-Type': 'application/json',\n },\n }\n )\n}\n\nexport type ResponseError = Response & { type: 'error' }\n\n/**\n * A key on the error a mocked `Response.error()` destroys the socket\n * with, referencing that error response. Allows the client-side\n * interceptors (e.g. fetch) to surface the error response to the\n * consumer instead of the internal socket error.\n */\nexport const kErrorResponse = Symbol('kErrorResponse')\n\n/**\n * Get the mocked error response that caused the given error, if any.\n */\nexport function getErrorResponse(error: unknown): ResponseError | undefined {\n if (\n error instanceof Error &&\n kErrorResponse in error &&\n isResponseError(error[kErrorResponse])\n ) {\n return error[kErrorResponse]\n }\n\n return undefined\n}\n\n/**\n * Check if the given response is a `Response.error()`.\n *\n * @note Some environments, like Miniflare (Cloudflare) do not\n * implement the \"Response.type\" property and throw on its access.\n * Safely check if we can access \"type\" on \"Response\" before continuing.\n * @see https://github.com/mswjs/msw/issues/1834\n */\nexport function isResponseError(response: unknown): response is ResponseError {\n return (\n response != null &&\n response instanceof Response &&\n isPropertyAccessible(response, 'type') &&\n response.type === 'error'\n )\n}\n\n/**\n * Check if the given value is a `Response` or a Response-like object.\n * This is different from `value instanceof Response` because it supports\n * custom `Response` constructors, like the one when using Undici directly.\n */\nexport function isResponseLike(value: unknown): value is Response {\n return (\n isObject<Record<string, any>>(value, true) &&\n isPropertyAccessible(value, 'status') &&\n isPropertyAccessible(value, 'statusText') &&\n isPropertyAccessible(value, 'bodyUsed')\n )\n}\n","import { copyRawHeaders } from '../interceptors/ClientRequest/utils/record-raw-headers'\nimport { getValueBySymbol } from './get-value-by-symbol'\nimport { isResponseError } from './response-utils'\n\ninterface UndiciRequestState extends RequestInit {}\n\ninterface FetchRequestInit extends Omit<RequestInit, 'mode'> {\n mode?: RequestMode | 'websocket' | 'webtransport'\n duplex?: 'half' | 'full'\n}\n\nexport class FetchRequest extends Request {\n static #resolveProperty<T extends keyof FetchRequestInit & keyof Request>(\n input: RequestInfo | URL,\n init: FetchRequestInit = {},\n key: T\n ): FetchRequestInit[T] {\n return init[key] ?? (input instanceof Request ? input[key] : undefined)\n }\n\n /**\n * Check if the given request method is configurable.\n * @see https://fetch.spec.whatwg.org/#methods\n */\n static isConfigurableMethod(method: string): boolean {\n return method !== 'CONNECT' && method !== 'TRACE' && method !== 'TRACK'\n }\n\n static isMethodWithBody(method: string): boolean {\n return (\n method !== 'HEAD' &&\n method !== 'GET' &&\n FetchRequest.isConfigurableMethod(method)\n )\n }\n\n /**\n * Check if the given request `mode` is configurable.\n * @see https://fetch.spec.whatwg.org/#concept-request-mode\n */\n static isConfigurableMode(mode: string): boolean {\n return (\n mode !== 'navigate' && mode !== 'websocket' && mode !== 'webtransport'\n )\n }\n\n constructor(input: URL | RequestInfo, init?: FetchRequestInit) {\n const method = FetchRequest.#resolveProperty(input, init, 'method') || 'GET'\n const safeMethod = FetchRequest.isConfigurableMethod(method)\n ? method\n : 'GET'\n\n const hasExplicitBody = init != null && 'body' in init\n\n /**\n * Only include `body` in the super init when it needs to be overridden.\n * When `input` is a Request and no explicit body is in `init`, let the\n * Request constructor handle body transfer naturally so it properly\n * marks the original request's body as consumed (bodyUsed = true).\n */\n const bodyInit: { body?: BodyInit | null } = !FetchRequest.isMethodWithBody(\n method\n )\n ? { body: undefined }\n : hasExplicitBody\n ? { body: init.body }\n : {}\n\n const mode =\n (FetchRequest.#resolveProperty(input, init, 'mode') as RequestMode) ??\n undefined\n const safeMode = FetchRequest.isConfigurableMode(mode) ? mode : undefined\n\n super(input, {\n ...(init || {}),\n method: safeMethod,\n mode: safeMode,\n // @ts-expect-error Untyped Node.js property.\n duplex:\n init?.duplex ??\n (FetchRequest.isMethodWithBody(method) ? 'half' : undefined),\n ...bodyInit,\n })\n\n if (method !== safeMethod) {\n this.#setInternalProperty('method', method)\n }\n\n if (method === 'CONNECT') {\n const url = new URL(input instanceof Request ? input.url : input)\n\n let authority: string\n\n /**\n * @note Node.js has a bug parsing raw CONNECT requests URLs like\n * \"http://127.0.0.1:1337/localhost:80\". It would treat \"localhost:\" as a protocol.\n */\n if (url.protocol === 'localhost:') {\n authority = url.href\n } else {\n authority = url.pathname.replace(/^\\/+/, '')\n }\n\n /**\n * @note Define \"url\" as a getter because Undici uses their own\n * logic to resolve the \"request.url\" property. Simply reassigning\n * its value doesn't do anything. This is a destructive action\n * but it's safe because \"CONNECT\" requests are forbidden per fetch.\n */\n Object.defineProperty(this, 'url', {\n get: () => authority,\n enumerable: true,\n configurable: true,\n })\n }\n\n if (mode != null && mode !== safeMode) {\n this.#setInternalProperty('mode', mode)\n }\n }\n\n #setInternalProperty<T extends keyof Request>(\n key: T,\n value: Request[T]\n ): void {\n const internalState = getValueBySymbol<UndiciRequestState>('state', this)\n\n if (internalState) {\n Reflect.set(internalState, key, value)\n } else {\n Object.defineProperty(this, key, {\n value,\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n }\n}\n\nexport interface FetchResponseInit extends ResponseInit {\n url?: string\n}\n\ninterface UndiciResponseState {\n aborted: boolean\n rangeRequested: boolean\n timingAllowPassed: boolean\n requestIncludesCredentials: boolean\n type: ResponseType\n status: number\n statusText: string\n timingInfo: unknown\n cacheState: unknown\n headersList: Record<symbol, Map<string, unknown>>\n urlList: Array<URL>\n body?: {\n stream: ReadableStream\n source: unknown\n length: number\n }\n}\n\nconst kStatus = Symbol('kStatus')\nconst kUrl = Symbol('kUrl')\n\nexport class FetchResponse extends Response {\n static from(response: Response, init?: FetchResponseInit): FetchResponse {\n if (response instanceof FetchResponse) {\n return response\n }\n\n if (isResponseError(response)) {\n return response\n }\n\n const fetchResponse = new FetchResponse(response.body, {\n url: init?.url ?? response.url,\n status: init?.status || response.status,\n statusText: init?.statusText ?? response.statusText,\n headers: init?.headers ?? response.headers,\n })\n\n copyRawHeaders(response.headers, fetchResponse.headers)\n\n return fetchResponse\n }\n\n /**\n * Response status codes for responses that cannot have body.\n * @see https://fetch.spec.whatwg.org/#statuses\n */\n static readonly STATUS_CODES_WITHOUT_BODY = [101, 103, 204, 205, 304]\n\n static readonly STATUS_CODES_WITH_REDIRECT = [301, 302, 303, 307, 308]\n\n static isConfigurableStatusCode(status: number): boolean {\n return status >= 200 && status <= 599\n }\n\n static isRedirectResponse(status: number): boolean {\n return FetchResponse.STATUS_CODES_WITH_REDIRECT.includes(status)\n }\n\n /**\n * Returns a boolean indicating whether the given response status\n * code represents a response that can have a body.\n */\n static isResponseWithBody(status: number): boolean {\n return !FetchResponse.STATUS_CODES_WITHOUT_BODY.includes(status)\n }\n\n static setStatus(status: number, response: Response): void {\n /**\n * @note Undici keeps an internal \"Symbol(state)\" that holds\n * the actual value of response status. Update that in Node.js.\n */\n const internalState = getValueBySymbol<UndiciResponseState>(\n 'state',\n response\n )\n\n if (internalState) {\n internalState.status = status\n } else {\n Object.defineProperty(response, 'status', {\n value: status,\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n\n Object.defineProperty(response, kStatus, {\n value: status,\n enumerable: false,\n })\n }\n\n static setUrl(url: string | undefined, response: Response): void {\n if (!url || url === 'about:' || !URL.canParse(url)) {\n return\n }\n\n const state = getValueBySymbol<UndiciResponseState>('state', response)\n\n if (state) {\n // In Undici, push the URL to the internal list of URLs.\n // This will respect the `response.url` getter logic correctly.\n state.urlList.push(new URL(url))\n } else {\n // In other libraries, redefine the `url` property directly.\n Object.defineProperty(response, 'url', {\n value: url,\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n\n Object.defineProperty(response, kUrl, {\n value: url,\n enumerable: false,\n })\n }\n\n /**\n * Parses the given raw HTTP headers into a Fetch API `Headers` instance.\n */\n static parseRawHeaders(rawHeaders: Array<string>): Headers {\n const headers = new Headers()\n\n for (let line = 0; line < rawHeaders.length; line += 2) {\n headers.append(rawHeaders[line], rawHeaders[line + 1])\n }\n\n return headers\n }\n\n /**\n * Safely clones the given `Response`.\n * Coerces response clone exceptions into 500 mocked responses.\n * Handy in the environments that introduce arbitrary response\n * cloning restrictions, like \"101 Switching Protocols\" cloning\n * in \"miniflare\".\n */\n static clone(response: Response): Response {\n try {\n const clone = response.clone()\n return clone\n } catch (error) {\n return Response.json(\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : {},\n {\n status: 500,\n statusText: 'Unclonable Response',\n }\n )\n }\n }\n\n #status?: number\n #url?: string\n\n constructor(body?: BodyInit | null, init: FetchResponseInit = {}) {\n const status = init.status ?? 200\n const safeStatus = FetchResponse.isConfigurableStatusCode(status)\n ? status\n : 200\n const finalBody = FetchResponse.isResponseWithBody(status) ? body : null\n\n super(finalBody, {\n status: safeStatus,\n statusText: init.statusText,\n headers: init.headers,\n })\n\n /**\n * Since Node.js v24, Undici stores the Response state in an inaccessible field \"#state\".\n * Forward the modified status/URL to the cloned response manually.\n * @see https://github.com/nodejs/undici/blob/f734c87280e626c75f59aad55b65eb6a89cef392/lib/web/fetch/response.js#L242\n */\n if (status !== safeStatus) {\n FetchResponse.setStatus(status, this)\n }\n\n FetchResponse.setUrl(init.url, this)\n }\n\n public clone() {\n const clonedResponse = super.clone()\n\n const customStatus = Reflect.get(this, kStatus) as number | undefined\n\n if (customStatus) {\n FetchResponse.setStatus(customStatus, clonedResponse)\n }\n\n const customUrl = Reflect.get(this, kUrl) as string | undefined\n\n if (customUrl) {\n FetchResponse.setUrl(customUrl, clonedResponse)\n }\n\n return clonedResponse\n }\n}\n"],"mappings":"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"}
|
package/lib/node/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as Interceptor } from "./interceptor-C8qRPjxG.js";
|
|
2
2
|
import { t as BatchInterceptor } from "./batch-interceptor-DMOfd-9x.js";
|
|
3
|
-
import {
|
|
3
|
+
import { f as RequestController, n as FetchResponse, p as InterceptorError, t as FetchRequest } from "./fetch-utils-D-_xeRlK.js";
|
|
4
4
|
import { t as createRequestId } from "./create-request-id-DHo-fRTV.js";
|
|
5
5
|
import { n as encodeBuffer, t as decodeBuffer } from "./buffer-utils-B4FUq-l2.js";
|
|
6
6
|
import { t as resolveWebSocketUrl } from "./resolve-web-socket-url-CSvNPLGi.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as forwardHttpEvents, o as runInRequestContext, t as NodeHttpRequestSource } from "../../source-
|
|
1
|
+
import { i as forwardHttpEvents, o as runInRequestContext, t as NodeHttpRequestSource } from "../../source-DHVO1vzq.js";
|
|
2
2
|
import { t as Interceptor } from "../../interceptor-C8qRPjxG.js";
|
|
3
3
|
import { n as patchesRegistry } from "../../patches-registry-DxR5TEc-.js";
|
|
4
4
|
import http from "node:http";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as requestContext, i as forwardHttpEvents, t as NodeHttpRequestSource } from "../../source-
|
|
1
|
+
import { a as requestContext, i as forwardHttpEvents, t as NodeHttpRequestSource } from "../../source-DHVO1vzq.js";
|
|
2
2
|
import { n as createLogger, t as Interceptor } from "../../interceptor-C8qRPjxG.js";
|
|
3
|
-
import { t as FetchRequest } from "../../fetch-utils-
|
|
3
|
+
import { t as FetchRequest } from "../../fetch-utils-D-_xeRlK.js";
|
|
4
4
|
import { n as patchesRegistry } from "../../patches-registry-DxR5TEc-.js";
|
|
5
5
|
import { t as hasConfigurableGlobal } from "../../has-configurable-global-CT6-QYdg.js";
|
|
6
6
|
//#region src/interceptors/XMLHttpRequest/node.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as requestContext, i as forwardHttpEvents, t as NodeHttpRequestSource } from "../../source-
|
|
1
|
+
import { a as requestContext, i as forwardHttpEvents, t as NodeHttpRequestSource } from "../../source-DHVO1vzq.js";
|
|
2
2
|
import { t as Interceptor } from "../../interceptor-C8qRPjxG.js";
|
|
3
|
-
import { i as getErrorResponse } from "../../fetch-utils-
|
|
3
|
+
import { i as getErrorResponse } from "../../fetch-utils-D-_xeRlK.js";
|
|
4
4
|
import { n as patchesRegistry } from "../../patches-registry-DxR5TEc-.js";
|
|
5
5
|
import { t as hasConfigurableGlobal } from "../../has-configurable-global-CT6-QYdg.js";
|
|
6
6
|
//#region src/interceptors/fetch/node.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as forwardHttpEvents, t as NodeHttpRequestSource } from "../../source-
|
|
1
|
+
import { i as forwardHttpEvents, t as NodeHttpRequestSource } from "../../source-DHVO1vzq.js";
|
|
2
2
|
import { t as Interceptor } from "../../interceptor-C8qRPjxG.js";
|
|
3
3
|
//#region src/interceptors/http/index.ts
|
|
4
4
|
/**
|
|
@@ -144,6 +144,7 @@ declare class TcpSocketController extends SocketController {
|
|
|
144
144
|
protected readonly createConnection: () => net.Socket;
|
|
145
145
|
serverSocket: net.Socket;
|
|
146
146
|
protected pendingConnection: PromiseWithResolvers<[TcpWrap, TcpHandle]>;
|
|
147
|
+
private removePassthroughSocketListeners?;
|
|
147
148
|
constructor(socket: net.Socket, createConnection: () => net.Socket, connectionOptions?: NetworkConnectionOptions);
|
|
148
149
|
/**
|
|
149
150
|
* Reset this controller to the pending state so the next exchange
|
|
@@ -192,6 +193,11 @@ declare class TcpSocketController extends SocketController {
|
|
|
192
193
|
uncorkReads(): void;
|
|
193
194
|
claim(): void;
|
|
194
195
|
passthrough(flushPendingData?: FlushPendingDataFunction): net.Socket;
|
|
196
|
+
/**
|
|
197
|
+
* Forward events for the lifetime of the connection, including while
|
|
198
|
+
* it is idle in an agent pool. Reusing it must not add more listeners.
|
|
199
|
+
*/
|
|
200
|
+
protected addPassthroughSocketListeners(realSocket: net.Socket): () => void;
|
|
195
201
|
}
|
|
196
202
|
declare class TlsSocketController extends TcpSocketController {
|
|
197
203
|
#private;
|
|
@@ -201,6 +207,7 @@ declare class TlsSocketController extends TcpSocketController {
|
|
|
201
207
|
protected emulateConnect(): void;
|
|
202
208
|
claim(): void;
|
|
203
209
|
passthrough(flushPendingData?: FlushPendingDataFunction): tls.TLSSocket;
|
|
210
|
+
protected addPassthroughSocketListeners(realSocket: net.Socket): () => void;
|
|
204
211
|
}
|
|
205
212
|
//#endregion
|
|
206
213
|
//#region src/utils/internal-connection.d.ts
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as SocketInterceptor } from "../../net-
|
|
1
|
+
import { t as SocketInterceptor } from "../../net-Bh16MP4u.js";
|
|
2
2
|
export { SocketInterceptor };
|
|
@@ -482,7 +482,8 @@ var TcpSocketController = class extends SocketController {
|
|
|
482
482
|
* must not close the client socket).
|
|
483
483
|
*/
|
|
484
484
|
if (this.#passthroughSocket) {
|
|
485
|
-
this
|
|
485
|
+
this.removePassthroughSocketListeners?.();
|
|
486
|
+
this.#passthroughSocket.destroy();
|
|
486
487
|
this.#passthroughSocket = null;
|
|
487
488
|
/**
|
|
488
489
|
* @note The handle swapped in from the destroyed connection,
|
|
@@ -966,11 +967,13 @@ var TcpSocketController = class extends SocketController {
|
|
|
966
967
|
const createRealSocket = () => {
|
|
967
968
|
const realSocket = this.#retargetedConnectionOptions ? this.#createRetargetedConnection(this.#retargetedConnectionOptions) : this.createConnection();
|
|
968
969
|
realSocket[kPatched] = true;
|
|
970
|
+
realSocket.allowHalfOpen = true;
|
|
969
971
|
if (this.socket.timeout != null) realSocket.setTimeout(this.socket.timeout);
|
|
970
972
|
return realSocket;
|
|
971
973
|
};
|
|
972
974
|
const realSocket = this.#passthroughSocket && !this.#passthroughSocket.destroyed ? this.#passthroughSocket : createRealSocket();
|
|
973
|
-
|
|
975
|
+
const isNewConnection = realSocket !== this.#passthroughSocket;
|
|
976
|
+
this.#passthroughSocket = realSocket;
|
|
974
977
|
if (this.#bufferedWrites.length === 0) logger$1.verbose("passthrough with empty writes buffer (state: %d)", this.readyState);
|
|
975
978
|
/**
|
|
976
979
|
* Flush any writes during the pending phase to the passthrough socket.
|
|
@@ -995,8 +998,10 @@ var TcpSocketController = class extends SocketController {
|
|
|
995
998
|
this.socket.address = realSocket.address.bind(realSocket);
|
|
996
999
|
this.socket.removeListener("drain", this.#onMockSocketDrain);
|
|
997
1000
|
this.socket.on("drain", this.#onMockSocketDrain);
|
|
998
|
-
|
|
999
|
-
|
|
1001
|
+
if (isNewConnection) {
|
|
1002
|
+
this.removePassthroughSocketListeners = this.addPassthroughSocketListeners(realSocket);
|
|
1003
|
+
realSocket.once("close", this.removePassthroughSocketListeners);
|
|
1004
|
+
}
|
|
1000
1005
|
/**
|
|
1001
1006
|
* @note Forward the client's half-close, unless the real handle
|
|
1002
1007
|
* is already swapped in — the client's own shutdown then reaches
|
|
@@ -1010,6 +1015,16 @@ var TcpSocketController = class extends SocketController {
|
|
|
1010
1015
|
return realSocket;
|
|
1011
1016
|
}
|
|
1012
1017
|
/**
|
|
1018
|
+
* Forward events for the lifetime of the connection, including while
|
|
1019
|
+
* it is idle in an agent pool. Reusing it must not add more listeners.
|
|
1020
|
+
*/
|
|
1021
|
+
addPassthroughSocketListeners(realSocket) {
|
|
1022
|
+
realSocket.once("connect", this.#onRealSocketConnect).on("connectionAttemptFailed", this.#onRealSocketConnectionAttemptFailed).on("connectionAttemptTimeout", this.#onRealSocketConnectionAttemptTimeout).on("data", this.#onRealSocketData).on("error", this.#onRealSocketError).on("end", this.#onRealSocketEnd).on("close", this.#onRealSocketClose);
|
|
1023
|
+
return () => {
|
|
1024
|
+
realSocket.removeListener("connect", this.#onRealSocketConnect).removeListener("connectionAttemptFailed", this.#onRealSocketConnectionAttemptFailed).removeListener("connectionAttemptTimeout", this.#onRealSocketConnectionAttemptTimeout).removeListener("data", this.#onRealSocketData).removeListener("error", this.#onRealSocketError).removeListener("end", this.#onRealSocketEnd).removeListener("close", this.#onRealSocketClose);
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
/**
|
|
1013
1028
|
* Create the passthrough connection to the target this controller
|
|
1014
1029
|
* was retargeted to (see `reset()`). The original `createConnection`
|
|
1015
1030
|
* dials the originally requested target and cannot serve retargeted
|
|
@@ -1181,17 +1196,28 @@ var TlsSocketController = class extends TcpSocketController {
|
|
|
1181
1196
|
# Assertion failed: !wrap->started_
|
|
1182
1197
|
*/
|
|
1183
1198
|
for (const connectListener of this.socket.listeners("connect")) if (connectListener === this.socket._start || "listener" in connectListener && connectListener.listener === this.socket._start) this.socket.removeListener("connect", connectListener);
|
|
1184
|
-
realSocket.on("secure", () => {
|
|
1185
|
-
this.socket.emit("secure");
|
|
1186
|
-
}).on("session", (...args) => {
|
|
1187
|
-
this.socket.emit("session", ...args);
|
|
1188
|
-
}).on("keylog", (...args) => {
|
|
1189
|
-
this.socket.emit("keylog", ...args);
|
|
1190
|
-
}).on("OCSPResponse", (...args) => {
|
|
1191
|
-
this.socket.emit("OCSPResponse", ...args);
|
|
1192
|
-
});
|
|
1193
1199
|
return realSocket;
|
|
1194
1200
|
}
|
|
1201
|
+
#onRealSocketSecure = () => {
|
|
1202
|
+
this.socket.emit("secure");
|
|
1203
|
+
};
|
|
1204
|
+
#onRealSocketSession = (session) => {
|
|
1205
|
+
this.socket.emit("session", session);
|
|
1206
|
+
};
|
|
1207
|
+
#onRealSocketKeylog = (line) => {
|
|
1208
|
+
this.socket.emit("keylog", line);
|
|
1209
|
+
};
|
|
1210
|
+
#onRealSocketOCSPResponse = (response) => {
|
|
1211
|
+
this.socket.emit("OCSPResponse", response);
|
|
1212
|
+
};
|
|
1213
|
+
addPassthroughSocketListeners(realSocket) {
|
|
1214
|
+
const removeTcpSocketListeners = super.addPassthroughSocketListeners(realSocket);
|
|
1215
|
+
realSocket.on("secure", this.#onRealSocketSecure).on("session", this.#onRealSocketSession).on("keylog", this.#onRealSocketKeylog).on("OCSPResponse", this.#onRealSocketOCSPResponse);
|
|
1216
|
+
return () => {
|
|
1217
|
+
removeTcpSocketListeners();
|
|
1218
|
+
realSocket.removeListener("secure", this.#onRealSocketSecure).removeListener("session", this.#onRealSocketSession).removeListener("keylog", this.#onRealSocketKeylog).removeListener("OCSPResponse", this.#onRealSocketOCSPResponse);
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1195
1221
|
};
|
|
1196
1222
|
//#endregion
|
|
1197
1223
|
//#region src/interceptors/net/utils/normalize-tls-connect-args.ts
|
|
@@ -1478,4 +1504,4 @@ var SocketInterceptor = class extends Interceptor {
|
|
|
1478
1504
|
//#endregion
|
|
1479
1505
|
export { unwrapPendingData as i, SocketController as n, kRawSocket as r, SocketInterceptor as t };
|
|
1480
1506
|
|
|
1481
|
-
//# sourceMappingURL=net-
|
|
1507
|
+
//# sourceMappingURL=net-Bh16MP4u.js.map
|