@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,8 +1,8 @@
|
|
|
1
1
|
import { n as createLogger, r as formatRequest, t as Interceptor } from "./interceptor-C8qRPjxG.js";
|
|
2
|
-
import { a as isResponseError, c as isObject, d as
|
|
2
|
+
import { a as isResponseError, c as isObject, d as recordRawFetchHeaders, f as RequestController, l as copyRawHeaders, n as FetchResponse, o as isResponseLike, p as InterceptorError, r as createServerErrorResponse, s as kErrorResponse, t as FetchRequest, u as getRawFetchHeaders } from "./fetch-utils-D-_xeRlK.js";
|
|
3
3
|
import { t as createRequestId } from "./create-request-id-DHo-fRTV.js";
|
|
4
4
|
import { r as toBuffer } from "./buffer-utils-B4FUq-l2.js";
|
|
5
|
-
import { i as unwrapPendingData, n as SocketController, r as kRawSocket, t as SocketInterceptor } from "./net-
|
|
5
|
+
import { i as unwrapPendingData, n as SocketController, r as kRawSocket, t as SocketInterceptor } from "./net-Bh16MP4u.js";
|
|
6
6
|
import { TypedEvent } from "rettime";
|
|
7
7
|
import { invariant } from "outvariant";
|
|
8
8
|
import { IncomingMessage, METHODS, STATUS_CODES, ServerResponse } from "node:http";
|
|
@@ -1573,6 +1573,56 @@ async function handleRequest(options) {
|
|
|
1573
1573
|
return options.controller.handled;
|
|
1574
1574
|
}
|
|
1575
1575
|
//#endregion
|
|
1576
|
+
//#region src/utils/clone-response.ts
|
|
1577
|
+
/** Clone for observers without letting their unread body block caller cancellation. */
|
|
1578
|
+
function cloneResponse(response) {
|
|
1579
|
+
const clone = FetchResponse.clone(response);
|
|
1580
|
+
if (!response.body || !clone.body) return [response, clone];
|
|
1581
|
+
const observer = wrapResponse(clone);
|
|
1582
|
+
return [wrapResponse(response, observer.cancel).response, observer.response];
|
|
1583
|
+
}
|
|
1584
|
+
function wrapResponse(response, onCancel) {
|
|
1585
|
+
const body = response.body;
|
|
1586
|
+
const reader = body.getReader();
|
|
1587
|
+
const cancel = (reason) => {
|
|
1588
|
+
return body.locked ? reader.cancel(reason) : body.cancel(reason);
|
|
1589
|
+
};
|
|
1590
|
+
const wrappedResponse = new FetchResponse(new ReadableStream({
|
|
1591
|
+
async pull(controller) {
|
|
1592
|
+
try {
|
|
1593
|
+
const { done, value } = await reader.read();
|
|
1594
|
+
if (done) {
|
|
1595
|
+
controller.close();
|
|
1596
|
+
reader.releaseLock();
|
|
1597
|
+
return;
|
|
1598
|
+
}
|
|
1599
|
+
controller.enqueue(value);
|
|
1600
|
+
} catch (error) {
|
|
1601
|
+
controller.error(error);
|
|
1602
|
+
reader.releaseLock();
|
|
1603
|
+
}
|
|
1604
|
+
},
|
|
1605
|
+
async cancel(reason) {
|
|
1606
|
+
try {
|
|
1607
|
+
const cancellation = cancel(reason);
|
|
1608
|
+
if (onCancel) await Promise.all([cancellation, onCancel(reason)]);
|
|
1609
|
+
else cancellation.catch(() => {});
|
|
1610
|
+
} finally {
|
|
1611
|
+
reader.releaseLock();
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
}, { highWaterMark: 0 }), response);
|
|
1615
|
+
copyRawHeaders(response.headers, wrappedResponse.headers);
|
|
1616
|
+
Object.defineProperties(wrappedResponse, {
|
|
1617
|
+
type: { value: response.type },
|
|
1618
|
+
redirected: { value: response.redirected }
|
|
1619
|
+
});
|
|
1620
|
+
return {
|
|
1621
|
+
response: wrappedResponse,
|
|
1622
|
+
cancel
|
|
1623
|
+
};
|
|
1624
|
+
}
|
|
1625
|
+
//#endregion
|
|
1576
1626
|
//#region src/interceptors/http/source.ts
|
|
1577
1627
|
const httpLogger = createLogger("http-request");
|
|
1578
1628
|
/**
|
|
@@ -1636,258 +1686,265 @@ var NodeHttpRequestSource = class extends Interceptor {
|
|
|
1636
1686
|
abortPendingRequest?.();
|
|
1637
1687
|
realSocketDestroy(error, callback);
|
|
1638
1688
|
};
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
}
|
|
1689
|
+
const addRequestDataListener = () => {
|
|
1690
|
+
const executeRequestParser = (parser, chunk) => {
|
|
1691
|
+
if (parser.execute(chunk) !== null) {
|
|
1692
|
+
socket.removeListener("data", onRequestData);
|
|
1693
|
+
parser.free();
|
|
1694
|
+
requestParser = void 0;
|
|
1695
|
+
}
|
|
1696
|
+
};
|
|
1648
1697
|
/**
|
|
1649
|
-
* @note
|
|
1650
|
-
*
|
|
1651
|
-
* the tunnel target. The parser stopped at the tunnel boundary
|
|
1652
|
-
* (HTTP upgrade semantics), so tear it down and detect the
|
|
1653
|
-
* tunneled protocol anew, like on a fresh connection.
|
|
1698
|
+
* @note Inspect the first sent packet to determine the protocol,
|
|
1699
|
+
* including when entering a mocked "CONNECT" tunnel.
|
|
1654
1700
|
*/
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
* @note Retarget the connection to the tunnel authority.
|
|
1661
|
-
* The exchanges that follow belong to the tunnel target,
|
|
1662
|
-
* so an unclaimed exchange (HTTP or not) must pass through
|
|
1663
|
-
* to that target — not to the proxy, which never actually
|
|
1664
|
-
* established this tunnel — like a real established tunnel
|
|
1665
|
-
* relays its traffic.
|
|
1666
|
-
*/
|
|
1667
|
-
socketController.reset({
|
|
1668
|
-
host: tunnelUrl.hostname,
|
|
1669
|
-
port: Number(tunnelUrl.port) || 80,
|
|
1670
|
-
path: null
|
|
1671
|
-
});
|
|
1672
|
-
}
|
|
1673
|
-
if (requestParser) {
|
|
1674
|
-
requestParser.execute(toBuffer(chunk));
|
|
1675
|
-
return;
|
|
1676
|
-
}
|
|
1677
|
-
const httpMessage = chunk.toString();
|
|
1678
|
-
const httpMethod = httpMessage.split(" ")[0] || "";
|
|
1679
|
-
if (!METHODS.includes(httpMethod.toUpperCase())) {
|
|
1680
|
-
isHttpConnection = false;
|
|
1681
|
-
socketController.decline();
|
|
1682
|
-
return;
|
|
1683
|
-
}
|
|
1684
|
-
isHttpConnection = true;
|
|
1685
|
-
const baseUrl = tunnelUrl ?? connectionOptionsToUrl(connectionOptions, socket);
|
|
1686
|
-
httpLogger.verbose("handling http message %o", {
|
|
1687
|
-
httpMessage,
|
|
1688
|
-
httpMethod,
|
|
1689
|
-
baseUrl
|
|
1690
|
-
});
|
|
1691
|
-
const requestContextValue = requestContext.getStore() ?? connectionRequestContext;
|
|
1692
|
-
const initiator = requestContextValue?.initiator || socket;
|
|
1693
|
-
requestParser = new HttpRequestParser({
|
|
1694
|
-
onError: stopParsingRequests,
|
|
1695
|
-
connectionOptions: {
|
|
1696
|
-
method: httpMethod,
|
|
1697
|
-
url: baseUrl
|
|
1698
|
-
},
|
|
1701
|
+
const onRequestData = (chunk) => {
|
|
1702
|
+
if (isHttpConnection === false) {
|
|
1703
|
+
socketController.decline();
|
|
1704
|
+
return;
|
|
1705
|
+
}
|
|
1699
1706
|
/**
|
|
1700
|
-
* @note
|
|
1701
|
-
*
|
|
1702
|
-
*
|
|
1703
|
-
*
|
|
1704
|
-
* (e.g. leaking a mocked request to the server of a
|
|
1705
|
-
* previously passed-through exchange).
|
|
1707
|
+
* @note A mocked "CONNECT" request has established a tunnel.
|
|
1708
|
+
* The data that follows belongs to a new exchange addressed to
|
|
1709
|
+
* the tunnel target. The previous parser was freed at the upgrade
|
|
1710
|
+
* boundary, so detect the tunneled protocol anew.
|
|
1706
1711
|
*/
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
},
|
|
1710
|
-
onRequest: async (parsedRequest, requestAbortController) => {
|
|
1711
|
-
const request = requestContextValue?.transformRequest?.(parsedRequest) ?? parsedRequest;
|
|
1712
|
+
if (tunnelUrl && !requestParser) {
|
|
1713
|
+
isHttpConnection = void 0;
|
|
1712
1714
|
/**
|
|
1713
|
-
* @note
|
|
1714
|
-
*
|
|
1715
|
-
*
|
|
1716
|
-
*
|
|
1717
|
-
*
|
|
1718
|
-
*
|
|
1715
|
+
* @note Retarget the connection to the tunnel authority.
|
|
1716
|
+
* The exchanges that follow belong to the tunnel target,
|
|
1717
|
+
* so an unclaimed exchange (HTTP or not) must pass through
|
|
1718
|
+
* to that target — not to the proxy, which never actually
|
|
1719
|
+
* established this tunnel — like a real established tunnel
|
|
1720
|
+
* relays its traffic.
|
|
1719
1721
|
*/
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
method: request.method,
|
|
1725
|
-
url: request.url
|
|
1722
|
+
socketController.reset({
|
|
1723
|
+
host: tunnelUrl.hostname,
|
|
1724
|
+
port: Number(tunnelUrl.port) || 80,
|
|
1725
|
+
path: null
|
|
1726
1726
|
});
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1727
|
+
}
|
|
1728
|
+
if (requestParser) {
|
|
1729
|
+
executeRequestParser(requestParser, toBuffer(chunk));
|
|
1730
|
+
return;
|
|
1731
|
+
}
|
|
1732
|
+
const httpMessage = chunk.toString();
|
|
1733
|
+
const httpMethod = httpMessage.split(" ")[0] || "";
|
|
1734
|
+
if (!METHODS.includes(httpMethod.toUpperCase())) {
|
|
1735
|
+
isHttpConnection = false;
|
|
1736
|
+
socketController.decline();
|
|
1737
|
+
return;
|
|
1738
|
+
}
|
|
1739
|
+
isHttpConnection = true;
|
|
1740
|
+
const baseUrl = tunnelUrl ?? connectionOptionsToUrl(connectionOptions, socket);
|
|
1741
|
+
httpLogger.verbose("handling http message %o", {
|
|
1742
|
+
httpMessage,
|
|
1743
|
+
httpMethod,
|
|
1744
|
+
baseUrl
|
|
1745
|
+
});
|
|
1746
|
+
const requestContextValue = requestContext.getStore() ?? connectionRequestContext;
|
|
1747
|
+
const initiator = requestContextValue?.initiator || socket;
|
|
1748
|
+
requestParser = new HttpRequestParser({
|
|
1749
|
+
onError: stopParsingRequests,
|
|
1750
|
+
connectionOptions: {
|
|
1751
|
+
method: httpMethod,
|
|
1752
|
+
url: baseUrl
|
|
1753
|
+
},
|
|
1754
|
+
/**
|
|
1755
|
+
* @note The message boundary ends the current exchange.
|
|
1756
|
+
* Schedule the controller reset so the next write on this
|
|
1757
|
+
* (kept-alive) socket opens a new exchange and buffers for
|
|
1758
|
+
* its own verdict instead of following the settled one
|
|
1759
|
+
* (e.g. leaking a mocked request to the server of a
|
|
1760
|
+
* previously passed-through exchange).
|
|
1761
|
+
*/
|
|
1762
|
+
onMessageComplete: () => {
|
|
1763
|
+
socketController.scheduleReset();
|
|
1764
|
+
},
|
|
1765
|
+
onRequest: async (parsedRequest, requestAbortController) => {
|
|
1766
|
+
const request = requestContextValue?.transformRequest?.(parsedRequest) ?? parsedRequest;
|
|
1767
|
+
/**
|
|
1768
|
+
* @note A subsequent request arriving on a kept-alive socket
|
|
1769
|
+
* that has already been handled (passed through or mocked).
|
|
1770
|
+
* Clients like Undici reuse sockets without emitting the
|
|
1771
|
+
* "free" event, so reset the controller here, at the HTTP
|
|
1772
|
+
* message boundary, to handle the new request from the
|
|
1773
|
+
* pending state again.
|
|
1774
|
+
*/
|
|
1775
|
+
if (socketController["readyState"] !== SocketController.PENDING) socketController.reset();
|
|
1776
|
+
const requestId = createRequestId();
|
|
1777
|
+
const requestLogger = requestContextValue?.logger ?? httpLogger;
|
|
1778
|
+
httpLogger.verbose("received a parsed HTTP request %o", {
|
|
1779
|
+
method: request.method,
|
|
1780
|
+
url: request.url
|
|
1781
|
+
});
|
|
1782
|
+
const requestController = new RequestController(request, {
|
|
1783
|
+
respondWith: async (rawResponse) => {
|
|
1784
|
+
httpLogger.verbose("respondWith() %o", {
|
|
1785
|
+
status: rawResponse.status,
|
|
1786
|
+
statusText: rawResponse.statusText,
|
|
1787
|
+
hasBody: rawResponse.body != null
|
|
1760
1788
|
});
|
|
1761
|
-
};
|
|
1762
|
-
if (responseClone) await this.emitter.emitAsPromise(new HttpResponseEvent({
|
|
1763
|
-
initiator,
|
|
1764
|
-
requestId,
|
|
1765
|
-
request: context.request,
|
|
1766
|
-
response: responseClone,
|
|
1767
|
-
responseType: "mock"
|
|
1768
|
-
}));
|
|
1769
|
-
if (socket.connecting) socket.once("connect", respond);
|
|
1770
|
-
else
|
|
1771
|
-
/**
|
|
1772
|
-
* @note Reused sockets stay connected between requests and will not
|
|
1773
|
-
* emit "connect" anymore. If that's the case, respond immediately.
|
|
1774
|
-
*/
|
|
1775
|
-
await respond();
|
|
1776
|
-
},
|
|
1777
|
-
errorWith: (reason) => {
|
|
1778
|
-
if (reason instanceof Error) socket.destroy(reason);
|
|
1779
|
-
},
|
|
1780
|
-
passthrough: () => {
|
|
1781
|
-
const realSocket = socketController.passthrough(isHttpConnection === false ? void 0 : this.#modifyHttpHeaders(context.request));
|
|
1782
|
-
if (isHttpConnection === false) return;
|
|
1783
|
-
if (this.emitter.listenerCount("response") > 0) {
|
|
1784
|
-
httpLogger.verbose("found \"response\" listener, corking socket reads");
|
|
1785
1789
|
/**
|
|
1786
|
-
*
|
|
1787
|
-
*
|
|
1788
|
-
*
|
|
1789
|
-
* resolve before the listeners are done. The real socket keeps
|
|
1790
|
-
* emitting data for the response parser meanwhile.
|
|
1790
|
+
* @note The client may destroy the socket (e.g. on request
|
|
1791
|
+
* abort) moments before a response arrives. A destroyed
|
|
1792
|
+
* socket cannot be claimed and has no one reading it.
|
|
1791
1793
|
*/
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
}
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1794
|
+
if (socket.destroyed) return;
|
|
1795
|
+
socketController.claim();
|
|
1796
|
+
const originalResponse = FetchResponse.from(rawResponse, { url: request.url });
|
|
1797
|
+
const [response, responseClone] = !isResponseError(originalResponse) && this.emitter.listenerCount("response") > 0 ? cloneResponse(originalResponse) : [originalResponse, null];
|
|
1798
|
+
/**
|
|
1799
|
+
* @note A successful mocked response to a "CONNECT"
|
|
1800
|
+
* request establishes a tunnel to the requested authority
|
|
1801
|
+
* (e.g. "127.0.0.1:80"). The exchange that follows on this
|
|
1802
|
+
* socket is addressed to that authority, not to the proxy.
|
|
1803
|
+
*/
|
|
1804
|
+
if (request.method === "CONNECT" && response.ok) {
|
|
1805
|
+
tunnelUrl = new URL(`http://${request.url}`);
|
|
1806
|
+
addRequestDataListener();
|
|
1807
|
+
}
|
|
1808
|
+
const respond = () => {
|
|
1809
|
+
return this.respondWith({
|
|
1810
|
+
socket: socketController[kRawSocket],
|
|
1811
|
+
request: context.request,
|
|
1812
|
+
response
|
|
1813
|
+
});
|
|
1814
|
+
};
|
|
1815
|
+
if (responseClone) await this.emitter.emitAsPromise(new HttpResponseEvent({
|
|
1816
|
+
initiator,
|
|
1817
|
+
requestId,
|
|
1818
|
+
request: context.request,
|
|
1819
|
+
response: responseClone,
|
|
1820
|
+
responseType: "mock"
|
|
1821
|
+
}));
|
|
1822
|
+
if (socket.connecting) socket.once("connect", respond);
|
|
1823
|
+
else
|
|
1824
|
+
/**
|
|
1825
|
+
* @note Reused sockets stay connected between requests and will not
|
|
1826
|
+
* emit "connect" anymore. If that's the case, respond immediately.
|
|
1827
|
+
*/
|
|
1828
|
+
await respond();
|
|
1829
|
+
},
|
|
1830
|
+
errorWith: (reason) => {
|
|
1831
|
+
if (reason instanceof Error) socket.destroy(reason);
|
|
1832
|
+
},
|
|
1833
|
+
passthrough: () => {
|
|
1834
|
+
const realSocket = socketController.passthrough(isHttpConnection === false ? void 0 : this.#modifyHttpHeaders(context.request));
|
|
1835
|
+
if (isHttpConnection === false) return;
|
|
1836
|
+
if (this.emitter.listenerCount("response") > 0) {
|
|
1837
|
+
httpLogger.verbose("found \"response\" listener, corking socket reads");
|
|
1838
|
+
/**
|
|
1839
|
+
* Suspend the delivery of the original response to the client
|
|
1840
|
+
* until the "response" event listeners settle. This guarantees
|
|
1841
|
+
* that the request promise (e.g. `await fetch()`) does not
|
|
1842
|
+
* resolve before the listeners are done. The real socket keeps
|
|
1843
|
+
* emitting data for the response parser meanwhile.
|
|
1844
|
+
*/
|
|
1845
|
+
socketController.corkReads();
|
|
1846
|
+
let responseParserDisposed = false;
|
|
1847
|
+
let responseComplete = false;
|
|
1848
|
+
let hasFinalResponse = false;
|
|
1849
|
+
const responseParser = new HttpResponseParser({
|
|
1850
|
+
onError: (error) => {
|
|
1851
|
+
disposeResponseParser(error);
|
|
1824
1852
|
socketController.uncorkReads();
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1853
|
+
},
|
|
1854
|
+
onMessageComplete: (status) => {
|
|
1855
|
+
responseComplete = status >= 200 || status === 101;
|
|
1856
|
+
},
|
|
1857
|
+
onResponse: async (response) => {
|
|
1858
|
+
hasFinalResponse = response.status >= 200 || response.status === 101;
|
|
1859
|
+
httpLogger.verbose("HTTP response parser parsed: %d %s", response.status, response.statusText);
|
|
1860
|
+
if (isResponseError(response)) {
|
|
1861
|
+
httpLogger.verbose("response is an error response, uncorking socket reads...");
|
|
1862
|
+
socketController.uncorkReads();
|
|
1863
|
+
return;
|
|
1864
|
+
}
|
|
1865
|
+
FetchResponse.setUrl(request.url, response);
|
|
1866
|
+
try {
|
|
1867
|
+
httpLogger.verbose("emitting \"response\" event");
|
|
1868
|
+
await this.emitter.emitAsPromise(new HttpResponseEvent({
|
|
1869
|
+
initiator,
|
|
1870
|
+
requestId,
|
|
1871
|
+
request: context.request,
|
|
1872
|
+
response,
|
|
1873
|
+
responseType: "original"
|
|
1874
|
+
}));
|
|
1875
|
+
} finally {
|
|
1876
|
+
httpLogger.verbose("uncorking socket reads");
|
|
1877
|
+
socketController.uncorkReads();
|
|
1878
|
+
/**
|
|
1879
|
+
* @note Informational responses other than
|
|
1880
|
+
* "101 Switching Protocols" are followed by a final
|
|
1881
|
+
* response on the same connection. Keep gating that
|
|
1882
|
+
* final response on the "response" event listeners.
|
|
1883
|
+
*/
|
|
1884
|
+
if (!responseParserDisposed && response.status < 200 && response.status !== 101) socketController.corkReads();
|
|
1885
|
+
}
|
|
1832
1886
|
}
|
|
1833
|
-
}
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1887
|
+
});
|
|
1888
|
+
const onResponseData = (chunk) => {
|
|
1889
|
+
responseParser.execute(chunk);
|
|
1890
|
+
if (responseComplete) disposeResponseParser();
|
|
1891
|
+
};
|
|
1892
|
+
const onResponseEnd = () => {
|
|
1893
|
+
disposeResponseParser();
|
|
1894
|
+
if (!hasFinalResponse) socketController.uncorkReads();
|
|
1895
|
+
};
|
|
1896
|
+
const disposeResponseParser = (error) => {
|
|
1897
|
+
responseParserDisposed = true;
|
|
1898
|
+
realSocket.removeListener("data", onResponseData);
|
|
1899
|
+
realSocket.removeListener("end", onResponseEnd);
|
|
1900
|
+
realSocket.removeListener("close", onResponseEnd);
|
|
1901
|
+
responseParser.free(error);
|
|
1902
|
+
};
|
|
1903
|
+
realSocket.on("data", onResponseData).once("end", onResponseEnd).once("close", onResponseEnd);
|
|
1904
|
+
}
|
|
1850
1905
|
}
|
|
1906
|
+
}, {
|
|
1907
|
+
logger: requestLogger,
|
|
1908
|
+
requestId
|
|
1909
|
+
});
|
|
1910
|
+
invariant(socketController["readyState"] === SocketController.PENDING, "CANNOT HANDLE ALREADY HANDLED REQUEST", request.method, request.url, socketController["readyState"]);
|
|
1911
|
+
/**
|
|
1912
|
+
* @note Create a request resolution context.
|
|
1913
|
+
* This is so modifications to the "request" in upstream interceptors
|
|
1914
|
+
* are correctly picked up by the underlying HTTP interceptor.
|
|
1915
|
+
*/
|
|
1916
|
+
const context = {
|
|
1917
|
+
initiator,
|
|
1918
|
+
requestId,
|
|
1919
|
+
request,
|
|
1920
|
+
controller: requestController,
|
|
1921
|
+
emitter: this.emitter,
|
|
1922
|
+
logger: requestLogger
|
|
1923
|
+
};
|
|
1924
|
+
/**
|
|
1925
|
+
* @note The client destroying the socket while the request
|
|
1926
|
+
* is still pending means the request was aborted (e.g. via
|
|
1927
|
+
* `AbortController`). Abort the parsed request so its
|
|
1928
|
+
* handling settles and late interactions with the request
|
|
1929
|
+
* controller become controlled errors.
|
|
1930
|
+
*/
|
|
1931
|
+
abortPendingRequest = () => {
|
|
1932
|
+
if (requestController.readyState === RequestController.PENDING) requestAbortController.abort();
|
|
1933
|
+
};
|
|
1934
|
+
pendingRequestController = requestController;
|
|
1935
|
+
try {
|
|
1936
|
+
await handleRequest(context);
|
|
1937
|
+
} finally {
|
|
1938
|
+
pendingRequestController = void 0;
|
|
1939
|
+
abortPendingRequest = void 0;
|
|
1851
1940
|
}
|
|
1852
|
-
}, {
|
|
1853
|
-
logger: requestLogger,
|
|
1854
|
-
requestId
|
|
1855
|
-
});
|
|
1856
|
-
invariant(socketController["readyState"] === SocketController.PENDING, "CANNOT HANDLE ALREADY HANDLED REQUEST", request.method, request.url, socketController["readyState"]);
|
|
1857
|
-
/**
|
|
1858
|
-
* @note Create a request resolution context.
|
|
1859
|
-
* This is so modifications to the "request" in upstream interceptors
|
|
1860
|
-
* are correctly picked up by the underlying HTTP interceptor.
|
|
1861
|
-
*/
|
|
1862
|
-
const context = {
|
|
1863
|
-
initiator,
|
|
1864
|
-
requestId,
|
|
1865
|
-
request,
|
|
1866
|
-
controller: requestController,
|
|
1867
|
-
emitter: this.emitter,
|
|
1868
|
-
logger: requestLogger
|
|
1869
|
-
};
|
|
1870
|
-
/**
|
|
1871
|
-
* @note The client destroying the socket while the request
|
|
1872
|
-
* is still pending means the request was aborted (e.g. via
|
|
1873
|
-
* `AbortController`). Abort the parsed request so its
|
|
1874
|
-
* handling settles and late interactions with the request
|
|
1875
|
-
* controller become controlled errors.
|
|
1876
|
-
*/
|
|
1877
|
-
abortPendingRequest = () => {
|
|
1878
|
-
if (requestController.readyState === RequestController.PENDING) requestAbortController.abort();
|
|
1879
|
-
};
|
|
1880
|
-
pendingRequestController = requestController;
|
|
1881
|
-
try {
|
|
1882
|
-
await handleRequest(context);
|
|
1883
|
-
} finally {
|
|
1884
|
-
pendingRequestController = void 0;
|
|
1885
|
-
abortPendingRequest = void 0;
|
|
1886
1941
|
}
|
|
1887
|
-
}
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1942
|
+
});
|
|
1943
|
+
executeRequestParser(requestParser, toBuffer(chunk));
|
|
1944
|
+
};
|
|
1945
|
+
socket.on("data", onRequestData);
|
|
1946
|
+
};
|
|
1947
|
+
addRequestDataListener();
|
|
1891
1948
|
socket.on("close", () => requestParser?.free());
|
|
1892
1949
|
}, { signal: controller.signal });
|
|
1893
1950
|
}
|
|
@@ -2076,4 +2133,4 @@ var NodeHttpRequestSource = class extends Interceptor {
|
|
|
2076
2133
|
//#endregion
|
|
2077
2134
|
export { requestContext as a, forwardHttpEvents as i, handleRequest as n, runInRequestContext as o, HttpResponseEvent as r, NodeHttpRequestSource as t };
|
|
2078
2135
|
|
|
2079
|
-
//# sourceMappingURL=source-
|
|
2136
|
+
//# sourceMappingURL=source-DHVO1vzq.js.map
|