@mswjs/interceptors 0.39.8 → 0.41.0

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.
Files changed (282) hide show
  1. package/ClientRequest/package.json +7 -2
  2. package/RemoteHttpInterceptor/package.json +7 -2
  3. package/WebSocket/package.json +9 -2
  4. package/XMLHttpRequest/package.json +9 -3
  5. package/fetch/package.json +9 -3
  6. package/lib/browser/Interceptor-2mUoKZL1.d.mts +65 -0
  7. package/lib/browser/Interceptor-Deczogc8.d.cts +65 -0
  8. package/lib/browser/XMLHttpRequest-BUfglQD1.cjs +761 -0
  9. package/lib/browser/XMLHttpRequest-BUfglQD1.cjs.map +1 -0
  10. package/lib/browser/XMLHttpRequest-DS5fc8Qs.mjs +756 -0
  11. package/lib/browser/XMLHttpRequest-DS5fc8Qs.mjs.map +1 -0
  12. package/lib/browser/bufferUtils-BiiO6HZv.mjs +20 -0
  13. package/lib/browser/bufferUtils-BiiO6HZv.mjs.map +1 -0
  14. package/lib/browser/bufferUtils-Uc0eRItL.cjs +38 -0
  15. package/lib/browser/bufferUtils-Uc0eRItL.cjs.map +1 -0
  16. package/lib/browser/createRequestId-Cs4oXfa1.cjs +205 -0
  17. package/lib/browser/createRequestId-Cs4oXfa1.cjs.map +1 -0
  18. package/lib/browser/createRequestId-DQcIlohW.mjs +170 -0
  19. package/lib/browser/createRequestId-DQcIlohW.mjs.map +1 -0
  20. package/lib/browser/fetch-BHcqM3z7.cjs +253 -0
  21. package/lib/browser/fetch-BHcqM3z7.cjs.map +1 -0
  22. package/lib/browser/fetch-DSJoynSF.mjs +248 -0
  23. package/lib/browser/fetch-DSJoynSF.mjs.map +1 -0
  24. package/lib/browser/getRawRequest-BTaNLFr0.mjs +218 -0
  25. package/lib/browser/getRawRequest-BTaNLFr0.mjs.map +1 -0
  26. package/lib/browser/getRawRequest-zx8rUJL2.cjs +259 -0
  27. package/lib/browser/getRawRequest-zx8rUJL2.cjs.map +1 -0
  28. package/lib/browser/glossary-BdLS4k1H.d.cts +70 -0
  29. package/lib/browser/glossary-gEEJhK4S.d.mts +70 -0
  30. package/lib/browser/handleRequest-DI6a7Dty.cjs +189 -0
  31. package/lib/browser/handleRequest-DI6a7Dty.cjs.map +1 -0
  32. package/lib/browser/handleRequest-DxGbCTbb.mjs +178 -0
  33. package/lib/browser/handleRequest-DxGbCTbb.mjs.map +1 -0
  34. package/lib/browser/hasConfigurableGlobal-C8kXFDic.mjs +33 -0
  35. package/lib/browser/hasConfigurableGlobal-C8kXFDic.mjs.map +1 -0
  36. package/lib/browser/hasConfigurableGlobal-D7S3l5h6.cjs +45 -0
  37. package/lib/browser/hasConfigurableGlobal-D7S3l5h6.cjs.map +1 -0
  38. package/lib/browser/index.cjs +68 -0
  39. package/lib/browser/index.cjs.map +1 -0
  40. package/lib/browser/index.d.cts +87 -0
  41. package/lib/browser/index.d.mts +87 -0
  42. package/lib/browser/index.mjs +49 -75
  43. package/lib/browser/index.mjs.map +1 -1
  44. package/lib/browser/interceptors/WebSocket/index.cjs +621 -0
  45. package/lib/browser/interceptors/WebSocket/index.cjs.map +1 -0
  46. package/lib/browser/interceptors/WebSocket/index.d.cts +277 -0
  47. package/lib/browser/interceptors/WebSocket/index.d.mts +277 -0
  48. package/lib/browser/interceptors/WebSocket/index.mjs +587 -694
  49. package/lib/browser/interceptors/WebSocket/index.mjs.map +1 -1
  50. package/lib/browser/interceptors/XMLHttpRequest/index.cjs +7 -0
  51. package/lib/browser/interceptors/XMLHttpRequest/index.d.cts +15 -0
  52. package/lib/browser/interceptors/XMLHttpRequest/index.d.mts +15 -0
  53. package/lib/browser/interceptors/XMLHttpRequest/index.mjs +7 -12
  54. package/lib/browser/interceptors/fetch/index.cjs +6 -0
  55. package/lib/browser/interceptors/fetch/index.d.cts +13 -0
  56. package/lib/browser/interceptors/fetch/index.d.mts +13 -0
  57. package/lib/browser/interceptors/fetch/index.mjs +6 -11
  58. package/lib/browser/presets/browser.cjs +17 -0
  59. package/lib/browser/presets/browser.cjs.map +1 -0
  60. package/lib/browser/presets/browser.d.cts +12 -0
  61. package/lib/browser/presets/browser.d.mts +14 -0
  62. package/lib/browser/presets/browser.mjs +15 -19
  63. package/lib/browser/presets/browser.mjs.map +1 -1
  64. package/lib/node/BatchInterceptor-3LnAnLTx.cjs +49 -0
  65. package/lib/node/BatchInterceptor-3LnAnLTx.cjs.map +1 -0
  66. package/lib/node/BatchInterceptor-D7mXzHcQ.d.mts +26 -0
  67. package/lib/node/BatchInterceptor-DFaBPilf.mjs +44 -0
  68. package/lib/node/BatchInterceptor-DFaBPilf.mjs.map +1 -0
  69. package/lib/node/BatchInterceptor-D_YqR8qU.d.cts +26 -0
  70. package/lib/node/ClientRequest-2rDe54Ui.cjs +1043 -0
  71. package/lib/node/ClientRequest-2rDe54Ui.cjs.map +1 -0
  72. package/lib/node/ClientRequest-Ca8Qykuv.mjs +1034 -0
  73. package/lib/node/ClientRequest-Ca8Qykuv.mjs.map +1 -0
  74. package/lib/node/Interceptor-DEazpLJd.d.mts +133 -0
  75. package/lib/node/Interceptor-DJ2akVWI.d.cts +133 -0
  76. package/lib/node/RemoteHttpInterceptor.cjs +154 -0
  77. package/lib/node/RemoteHttpInterceptor.cjs.map +1 -0
  78. package/lib/node/RemoteHttpInterceptor.d.cts +39 -0
  79. package/lib/node/RemoteHttpInterceptor.d.mts +39 -0
  80. package/lib/node/RemoteHttpInterceptor.mjs +145 -186
  81. package/lib/node/RemoteHttpInterceptor.mjs.map +1 -1
  82. package/lib/node/XMLHttpRequest-B7kJdYYI.cjs +763 -0
  83. package/lib/node/XMLHttpRequest-B7kJdYYI.cjs.map +1 -0
  84. package/lib/node/XMLHttpRequest-C8dIZpds.mjs +757 -0
  85. package/lib/node/XMLHttpRequest-C8dIZpds.mjs.map +1 -0
  86. package/lib/node/bufferUtils-DiCTqG-7.cjs +38 -0
  87. package/lib/node/bufferUtils-DiCTqG-7.cjs.map +1 -0
  88. package/lib/node/bufferUtils-_8XfKIfX.mjs +20 -0
  89. package/lib/node/bufferUtils-_8XfKIfX.mjs.map +1 -0
  90. package/lib/node/chunk-CbDLau6x.cjs +34 -0
  91. package/lib/node/fetch-BmXpK10r.cjs +272 -0
  92. package/lib/node/fetch-BmXpK10r.cjs.map +1 -0
  93. package/lib/node/fetch-G1DVwDKG.mjs +265 -0
  94. package/lib/node/fetch-G1DVwDKG.mjs.map +1 -0
  95. package/lib/node/fetchUtils-BaY5iWXw.cjs +419 -0
  96. package/lib/node/fetchUtils-BaY5iWXw.cjs.map +1 -0
  97. package/lib/node/fetchUtils-CoU35g3M.mjs +359 -0
  98. package/lib/node/fetchUtils-CoU35g3M.mjs.map +1 -0
  99. package/lib/node/getRawRequest-BavnMWh_.cjs +36 -0
  100. package/lib/node/getRawRequest-BavnMWh_.cjs.map +1 -0
  101. package/lib/node/getRawRequest-DnwmXyOW.mjs +24 -0
  102. package/lib/node/getRawRequest-DnwmXyOW.mjs.map +1 -0
  103. package/lib/node/glossary-BLKRyLBd.cjs +12 -0
  104. package/lib/node/glossary-BLKRyLBd.cjs.map +1 -0
  105. package/lib/node/glossary-glQBRnVD.mjs +6 -0
  106. package/lib/node/glossary-glQBRnVD.mjs.map +1 -0
  107. package/lib/node/handleRequest-Bb7Y-XLw.cjs +220 -0
  108. package/lib/node/handleRequest-Bb7Y-XLw.cjs.map +1 -0
  109. package/lib/node/handleRequest-Y97UwBbF.mjs +190 -0
  110. package/lib/node/handleRequest-Y97UwBbF.mjs.map +1 -0
  111. package/lib/node/hasConfigurableGlobal-C97fWuaA.cjs +26 -0
  112. package/lib/node/hasConfigurableGlobal-C97fWuaA.cjs.map +1 -0
  113. package/lib/node/hasConfigurableGlobal-DBJA0vjm.mjs +20 -0
  114. package/lib/node/hasConfigurableGlobal-DBJA0vjm.mjs.map +1 -0
  115. package/lib/node/index-BMbJ8FXL.d.cts +113 -0
  116. package/lib/node/index-C0YAQ36w.d.mts +113 -0
  117. package/lib/node/index.cjs +30 -0
  118. package/lib/node/index.cjs.map +1 -0
  119. package/lib/node/index.d.cts +66 -0
  120. package/lib/node/index.d.mts +66 -0
  121. package/lib/node/index.mjs +13 -39
  122. package/lib/node/index.mjs.map +1 -1
  123. package/lib/node/interceptors/ClientRequest/index.cjs +6 -0
  124. package/lib/node/interceptors/ClientRequest/index.d.cts +2 -0
  125. package/lib/node/interceptors/ClientRequest/index.d.mts +3 -0
  126. package/lib/node/interceptors/ClientRequest/index.mjs +6 -11
  127. package/lib/node/interceptors/XMLHttpRequest/index.cjs +6 -0
  128. package/lib/node/interceptors/XMLHttpRequest/index.d.cts +14 -0
  129. package/lib/node/interceptors/XMLHttpRequest/index.d.mts +14 -0
  130. package/lib/node/interceptors/XMLHttpRequest/index.mjs +6 -13
  131. package/lib/node/interceptors/fetch/index.cjs +5 -0
  132. package/lib/node/interceptors/fetch/index.d.cts +12 -0
  133. package/lib/node/interceptors/fetch/index.d.mts +12 -0
  134. package/lib/node/interceptors/fetch/index.mjs +5 -12
  135. package/lib/node/node-DwCc6iuP.mjs +27 -0
  136. package/lib/node/node-DwCc6iuP.mjs.map +1 -0
  137. package/lib/node/node-dKdAf3tC.cjs +39 -0
  138. package/lib/node/node-dKdAf3tC.cjs.map +1 -0
  139. package/lib/node/presets/node.cjs +22 -0
  140. package/lib/node/presets/node.cjs.map +1 -0
  141. package/lib/node/presets/node.d.cts +13 -0
  142. package/lib/node/presets/node.d.mts +15 -0
  143. package/lib/node/presets/node.mjs +18 -23
  144. package/lib/node/presets/node.mjs.map +1 -1
  145. package/lib/node/utils/node/index.cjs +4 -0
  146. package/lib/node/utils/node/{index.d.ts → index.d.cts} +5 -2
  147. package/lib/node/utils/node/index.d.mts +16 -0
  148. package/lib/node/utils/node/index.mjs +3 -10
  149. package/package.json +34 -59
  150. package/presets/browser/package.json +2 -3
  151. package/presets/node/package.json +7 -2
  152. package/src/RemoteHttpInterceptor.ts +18 -13
  153. package/src/RequestController.test.ts +78 -31
  154. package/src/RequestController.ts +63 -39
  155. package/src/index.ts +4 -0
  156. package/src/interceptors/ClientRequest/MockHttpSocket.ts +43 -9
  157. package/src/interceptors/ClientRequest/index.ts +14 -18
  158. package/src/interceptors/ClientRequest/utils/parserUtils.ts +48 -0
  159. package/src/interceptors/WebSocket/index.ts +4 -1
  160. package/src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts +45 -35
  161. package/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts +24 -21
  162. package/src/interceptors/XMLHttpRequest/utils/getBodyByteLength.test.ts +2 -2
  163. package/src/interceptors/fetch/index.ts +61 -50
  164. package/src/utils/handleRequest.ts +65 -95
  165. package/lib/browser/Interceptor-af98b768.d.ts +0 -63
  166. package/lib/browser/chunk-2HUMWGRD.js +0 -37
  167. package/lib/browser/chunk-2HUMWGRD.js.map +0 -1
  168. package/lib/browser/chunk-2QICSCCS.js +0 -238
  169. package/lib/browser/chunk-2QICSCCS.js.map +0 -1
  170. package/lib/browser/chunk-3RXCRGL2.mjs +0 -117
  171. package/lib/browser/chunk-3RXCRGL2.mjs.map +0 -1
  172. package/lib/browser/chunk-6HYIRFX2.mjs +0 -22
  173. package/lib/browser/chunk-6HYIRFX2.mjs.map +0 -1
  174. package/lib/browser/chunk-E3CCOBRX.js +0 -846
  175. package/lib/browser/chunk-E3CCOBRX.js.map +0 -1
  176. package/lib/browser/chunk-E7UVBHVO.mjs +0 -846
  177. package/lib/browser/chunk-E7UVBHVO.mjs.map +0 -1
  178. package/lib/browser/chunk-H74PGQ4Y.js +0 -296
  179. package/lib/browser/chunk-H74PGQ4Y.js.map +0 -1
  180. package/lib/browser/chunk-LK6DILFK.js +0 -22
  181. package/lib/browser/chunk-LK6DILFK.js.map +0 -1
  182. package/lib/browser/chunk-PTTUYYVR.mjs +0 -238
  183. package/lib/browser/chunk-PTTUYYVR.mjs.map +0 -1
  184. package/lib/browser/chunk-Q7K2XAEP.mjs +0 -296
  185. package/lib/browser/chunk-Q7K2XAEP.mjs.map +0 -1
  186. package/lib/browser/chunk-QED3Q6Z2.mjs +0 -169
  187. package/lib/browser/chunk-QED3Q6Z2.mjs.map +0 -1
  188. package/lib/browser/chunk-T7TBRNJZ.js +0 -117
  189. package/lib/browser/chunk-T7TBRNJZ.js.map +0 -1
  190. package/lib/browser/chunk-TIPR373R.js +0 -169
  191. package/lib/browser/chunk-TIPR373R.js.map +0 -1
  192. package/lib/browser/chunk-VYSDLBSS.mjs +0 -37
  193. package/lib/browser/chunk-VYSDLBSS.mjs.map +0 -1
  194. package/lib/browser/glossary-7152281e.d.ts +0 -69
  195. package/lib/browser/index.d.ts +0 -83
  196. package/lib/browser/index.js +0 -81
  197. package/lib/browser/index.js.map +0 -1
  198. package/lib/browser/interceptors/WebSocket/index.d.ts +0 -271
  199. package/lib/browser/interceptors/WebSocket/index.js +0 -721
  200. package/lib/browser/interceptors/WebSocket/index.js.map +0 -1
  201. package/lib/browser/interceptors/XMLHttpRequest/index.d.ts +0 -15
  202. package/lib/browser/interceptors/XMLHttpRequest/index.js +0 -12
  203. package/lib/browser/interceptors/XMLHttpRequest/index.js.map +0 -1
  204. package/lib/browser/interceptors/XMLHttpRequest/index.mjs.map +0 -1
  205. package/lib/browser/interceptors/fetch/index.d.ts +0 -14
  206. package/lib/browser/interceptors/fetch/index.js +0 -11
  207. package/lib/browser/interceptors/fetch/index.js.map +0 -1
  208. package/lib/browser/interceptors/fetch/index.mjs.map +0 -1
  209. package/lib/browser/presets/browser.d.ts +0 -15
  210. package/lib/browser/presets/browser.js +0 -21
  211. package/lib/browser/presets/browser.js.map +0 -1
  212. package/lib/node/BatchInterceptor-5b72232f.d.ts +0 -24
  213. package/lib/node/Interceptor-bc5a9d8e.d.ts +0 -130
  214. package/lib/node/RemoteHttpInterceptor.d.ts +0 -45
  215. package/lib/node/RemoteHttpInterceptor.js +0 -193
  216. package/lib/node/RemoteHttpInterceptor.js.map +0 -1
  217. package/lib/node/chunk-3CNGDJFB.mjs +0 -313
  218. package/lib/node/chunk-3CNGDJFB.mjs.map +0 -1
  219. package/lib/node/chunk-3GJB4JDF.mjs +0 -14
  220. package/lib/node/chunk-3GJB4JDF.mjs.map +0 -1
  221. package/lib/node/chunk-4NEYTVWD.mjs +0 -848
  222. package/lib/node/chunk-4NEYTVWD.mjs.map +0 -1
  223. package/lib/node/chunk-4YBV77DG.js +0 -32
  224. package/lib/node/chunk-4YBV77DG.js.map +0 -1
  225. package/lib/node/chunk-6HYIRFX2.mjs +0 -22
  226. package/lib/node/chunk-6HYIRFX2.mjs.map +0 -1
  227. package/lib/node/chunk-6YM4PLBI.mjs +0 -7
  228. package/lib/node/chunk-6YM4PLBI.mjs.map +0 -1
  229. package/lib/node/chunk-72ZIHMEB.js +0 -249
  230. package/lib/node/chunk-72ZIHMEB.js.map +0 -1
  231. package/lib/node/chunk-73NOP3T5.js +0 -7
  232. package/lib/node/chunk-73NOP3T5.js.map +0 -1
  233. package/lib/node/chunk-A7Q4RTDJ.mjs +0 -249
  234. package/lib/node/chunk-A7Q4RTDJ.mjs.map +0 -1
  235. package/lib/node/chunk-A7U44ARP.js +0 -268
  236. package/lib/node/chunk-A7U44ARP.js.map +0 -1
  237. package/lib/node/chunk-EKNRB5ZS.mjs +0 -1115
  238. package/lib/node/chunk-EKNRB5ZS.mjs.map +0 -1
  239. package/lib/node/chunk-IHJSPMYM.mjs +0 -268
  240. package/lib/node/chunk-IHJSPMYM.mjs.map +0 -1
  241. package/lib/node/chunk-LK6DILFK.js +0 -22
  242. package/lib/node/chunk-LK6DILFK.js.map +0 -1
  243. package/lib/node/chunk-N4ZZFE24.js +0 -1115
  244. package/lib/node/chunk-N4ZZFE24.js.map +0 -1
  245. package/lib/node/chunk-PFGO5BSM.js +0 -25
  246. package/lib/node/chunk-PFGO5BSM.js.map +0 -1
  247. package/lib/node/chunk-R6JVCM7X.js +0 -51
  248. package/lib/node/chunk-R6JVCM7X.js.map +0 -1
  249. package/lib/node/chunk-RC2XPCC4.mjs +0 -51
  250. package/lib/node/chunk-RC2XPCC4.mjs.map +0 -1
  251. package/lib/node/chunk-SMXZPJEA.js +0 -14
  252. package/lib/node/chunk-SMXZPJEA.js.map +0 -1
  253. package/lib/node/chunk-TJDMZZXE.mjs +0 -32
  254. package/lib/node/chunk-TJDMZZXE.mjs.map +0 -1
  255. package/lib/node/chunk-TX5GBTFY.mjs +0 -25
  256. package/lib/node/chunk-TX5GBTFY.mjs.map +0 -1
  257. package/lib/node/chunk-VV2LUF5K.js +0 -848
  258. package/lib/node/chunk-VV2LUF5K.js.map +0 -1
  259. package/lib/node/chunk-Z5LWCBZS.js +0 -313
  260. package/lib/node/chunk-Z5LWCBZS.js.map +0 -1
  261. package/lib/node/index.d.ts +0 -62
  262. package/lib/node/index.js +0 -43
  263. package/lib/node/index.js.map +0 -1
  264. package/lib/node/interceptors/ClientRequest/index.d.ts +0 -111
  265. package/lib/node/interceptors/ClientRequest/index.js +0 -11
  266. package/lib/node/interceptors/ClientRequest/index.js.map +0 -1
  267. package/lib/node/interceptors/ClientRequest/index.mjs.map +0 -1
  268. package/lib/node/interceptors/XMLHttpRequest/index.d.ts +0 -14
  269. package/lib/node/interceptors/XMLHttpRequest/index.js +0 -13
  270. package/lib/node/interceptors/XMLHttpRequest/index.js.map +0 -1
  271. package/lib/node/interceptors/XMLHttpRequest/index.mjs.map +0 -1
  272. package/lib/node/interceptors/fetch/index.d.ts +0 -13
  273. package/lib/node/interceptors/fetch/index.js +0 -12
  274. package/lib/node/interceptors/fetch/index.js.map +0 -1
  275. package/lib/node/interceptors/fetch/index.mjs.map +0 -1
  276. package/lib/node/presets/node.d.ts +0 -16
  277. package/lib/node/presets/node.js +0 -27
  278. package/lib/node/presets/node.js.map +0 -1
  279. package/lib/node/utils/node/index.js +0 -10
  280. package/lib/node/utils/node/index.js.map +0 -1
  281. package/lib/node/utils/node/index.mjs.map +0 -1
  282. package/src/utils/RequestController.ts +0 -21
@@ -0,0 +1,1034 @@
1
+ import { i as RequestController, o as INTERNAL_REQUEST_ID_HEADER_NAME, r as createRequestId, s as Interceptor, t as FetchResponse } from "./fetchUtils-CoU35g3M.mjs";
2
+ import { n as setRawRequest } from "./getRawRequest-DnwmXyOW.mjs";
3
+ import { a as isPropertyAccessible, i as emitAsync, r as isObject, t as handleRequest } from "./handleRequest-Y97UwBbF.mjs";
4
+ import { n as setRawRequestBodyStream } from "./node-DwCc6iuP.mjs";
5
+ import { Logger } from "@open-draft/logger";
6
+ import { invariant } from "outvariant";
7
+ import http, { IncomingMessage, STATUS_CODES, ServerResponse, globalAgent } from "node:http";
8
+ import https, { globalAgent as globalAgent$1 } from "node:https";
9
+ import net from "node:net";
10
+ import { HTTPParser } from "_http_common";
11
+ import { Readable } from "node:stream";
12
+ import { URL as URL$1, parse, urlToHttpOptions } from "node:url";
13
+ import { Agent } from "http";
14
+
15
+ //#region src/interceptors/Socket/utils/normalizeSocketWriteArgs.ts
16
+ /**
17
+ * Normalizes the arguments provided to the `Writable.prototype.write()`
18
+ * and `Writable.prototype.end()`.
19
+ */
20
+ function normalizeSocketWriteArgs(args) {
21
+ const normalized = [
22
+ args[0],
23
+ void 0,
24
+ void 0
25
+ ];
26
+ if (typeof args[1] === "string") normalized[1] = args[1];
27
+ else if (typeof args[1] === "function") normalized[2] = args[1];
28
+ if (typeof args[2] === "function") normalized[2] = args[2];
29
+ return normalized;
30
+ }
31
+
32
+ //#endregion
33
+ //#region src/interceptors/Socket/MockSocket.ts
34
+ var MockSocket = class extends net.Socket {
35
+ constructor(options) {
36
+ super();
37
+ this.options = options;
38
+ this.connecting = false;
39
+ this.connect();
40
+ this._final = (callback) => {
41
+ callback(null);
42
+ };
43
+ }
44
+ connect() {
45
+ this.connecting = true;
46
+ return this;
47
+ }
48
+ write(...args) {
49
+ const [chunk, encoding, callback] = normalizeSocketWriteArgs(args);
50
+ this.options.write(chunk, encoding, callback);
51
+ return true;
52
+ }
53
+ end(...args) {
54
+ const [chunk, encoding, callback] = normalizeSocketWriteArgs(args);
55
+ this.options.write(chunk, encoding, callback);
56
+ return super.end.apply(this, args);
57
+ }
58
+ push(chunk, encoding) {
59
+ this.options.read(chunk, encoding);
60
+ return super.push(chunk, encoding);
61
+ }
62
+ };
63
+
64
+ //#endregion
65
+ //#region src/interceptors/Socket/utils/baseUrlFromConnectionOptions.ts
66
+ function baseUrlFromConnectionOptions(options) {
67
+ if ("href" in options) return new URL(options.href);
68
+ const protocol = options.port === 443 ? "https:" : "http:";
69
+ const host = options.host;
70
+ const url = new URL(`${protocol}//${host}`);
71
+ if (options.port) url.port = options.port.toString();
72
+ if (options.path) url.pathname = options.path;
73
+ if (options.auth) {
74
+ const [username, password] = options.auth.split(":");
75
+ url.username = username;
76
+ url.password = password;
77
+ }
78
+ return url;
79
+ }
80
+
81
+ //#endregion
82
+ //#region src/interceptors/ClientRequest/utils/recordRawHeaders.ts
83
+ const kRawHeaders = Symbol("kRawHeaders");
84
+ const kRestorePatches = Symbol("kRestorePatches");
85
+ function recordRawHeader(headers, args, behavior) {
86
+ ensureRawHeadersSymbol(headers, []);
87
+ const rawHeaders = Reflect.get(headers, kRawHeaders);
88
+ if (behavior === "set") {
89
+ for (let index = rawHeaders.length - 1; index >= 0; index--) if (rawHeaders[index][0].toLowerCase() === args[0].toLowerCase()) rawHeaders.splice(index, 1);
90
+ }
91
+ rawHeaders.push(args);
92
+ }
93
+ /**
94
+ * Define the raw headers symbol on the given `Headers` instance.
95
+ * If the symbol already exists, this function does nothing.
96
+ */
97
+ function ensureRawHeadersSymbol(headers, rawHeaders) {
98
+ if (Reflect.has(headers, kRawHeaders)) return;
99
+ defineRawHeadersSymbol(headers, rawHeaders);
100
+ }
101
+ /**
102
+ * Define the raw headers symbol on the given `Headers` instance.
103
+ * If the symbol already exists, it gets overridden.
104
+ */
105
+ function defineRawHeadersSymbol(headers, rawHeaders) {
106
+ Object.defineProperty(headers, kRawHeaders, {
107
+ value: rawHeaders,
108
+ enumerable: false,
109
+ configurable: true
110
+ });
111
+ }
112
+ /**
113
+ * Patch the global `Headers` class to store raw headers.
114
+ * This is for compatibility with `IncomingMessage.prototype.rawHeaders`.
115
+ *
116
+ * @note Node.js has their own raw headers symbol but it
117
+ * only records the first header name in case of multi-value headers.
118
+ * Any other headers are normalized before comparing. This makes it
119
+ * incompatible with the `rawHeaders` format.
120
+ *
121
+ * let h = new Headers()
122
+ * h.append('X-Custom', 'one')
123
+ * h.append('x-custom', 'two')
124
+ * h[Symbol('headers map')] // Map { 'X-Custom' => 'one, two' }
125
+ */
126
+ function recordRawFetchHeaders() {
127
+ if (Reflect.get(Headers, kRestorePatches)) return Reflect.get(Headers, kRestorePatches);
128
+ const { Headers: OriginalHeaders, Request: OriginalRequest, Response: OriginalResponse } = globalThis;
129
+ const { set, append, delete: headersDeleteMethod } = Headers.prototype;
130
+ Object.defineProperty(Headers, kRestorePatches, {
131
+ value: () => {
132
+ Headers.prototype.set = set;
133
+ Headers.prototype.append = append;
134
+ Headers.prototype.delete = headersDeleteMethod;
135
+ globalThis.Headers = OriginalHeaders;
136
+ globalThis.Request = OriginalRequest;
137
+ globalThis.Response = OriginalResponse;
138
+ Reflect.deleteProperty(Headers, kRestorePatches);
139
+ },
140
+ enumerable: false,
141
+ configurable: true
142
+ });
143
+ Object.defineProperty(globalThis, "Headers", {
144
+ enumerable: true,
145
+ writable: true,
146
+ value: new Proxy(Headers, { construct(target, args, newTarget) {
147
+ const headersInit = args[0] || [];
148
+ if (headersInit instanceof Headers && Reflect.has(headersInit, kRawHeaders)) {
149
+ const headers$1 = Reflect.construct(target, [Reflect.get(headersInit, kRawHeaders)], newTarget);
150
+ ensureRawHeadersSymbol(headers$1, [...Reflect.get(headersInit, kRawHeaders)]);
151
+ return headers$1;
152
+ }
153
+ const headers = Reflect.construct(target, args, newTarget);
154
+ if (!Reflect.has(headers, kRawHeaders)) ensureRawHeadersSymbol(headers, Array.isArray(headersInit) ? headersInit : Object.entries(headersInit));
155
+ return headers;
156
+ } })
157
+ });
158
+ Headers.prototype.set = new Proxy(Headers.prototype.set, { apply(target, thisArg, args) {
159
+ recordRawHeader(thisArg, args, "set");
160
+ return Reflect.apply(target, thisArg, args);
161
+ } });
162
+ Headers.prototype.append = new Proxy(Headers.prototype.append, { apply(target, thisArg, args) {
163
+ recordRawHeader(thisArg, args, "append");
164
+ return Reflect.apply(target, thisArg, args);
165
+ } });
166
+ Headers.prototype.delete = new Proxy(Headers.prototype.delete, { apply(target, thisArg, args) {
167
+ const rawHeaders = Reflect.get(thisArg, kRawHeaders);
168
+ if (rawHeaders) {
169
+ for (let index = rawHeaders.length - 1; index >= 0; index--) if (rawHeaders[index][0].toLowerCase() === args[0].toLowerCase()) rawHeaders.splice(index, 1);
170
+ }
171
+ return Reflect.apply(target, thisArg, args);
172
+ } });
173
+ Object.defineProperty(globalThis, "Request", {
174
+ enumerable: true,
175
+ writable: true,
176
+ value: new Proxy(Request, { construct(target, args, newTarget) {
177
+ const request = Reflect.construct(target, args, newTarget);
178
+ const inferredRawHeaders = [];
179
+ if (typeof args[0] === "object" && args[0].headers != null) inferredRawHeaders.push(...inferRawHeaders(args[0].headers));
180
+ if (typeof args[1] === "object" && args[1].headers != null) inferredRawHeaders.push(...inferRawHeaders(args[1].headers));
181
+ if (inferredRawHeaders.length > 0) ensureRawHeadersSymbol(request.headers, inferredRawHeaders);
182
+ return request;
183
+ } })
184
+ });
185
+ Object.defineProperty(globalThis, "Response", {
186
+ enumerable: true,
187
+ writable: true,
188
+ value: new Proxy(Response, { construct(target, args, newTarget) {
189
+ const response = Reflect.construct(target, args, newTarget);
190
+ if (typeof args[1] === "object" && args[1].headers != null) ensureRawHeadersSymbol(response.headers, inferRawHeaders(args[1].headers));
191
+ return response;
192
+ } })
193
+ });
194
+ }
195
+ function restoreHeadersPrototype() {
196
+ if (!Reflect.get(Headers, kRestorePatches)) return;
197
+ Reflect.get(Headers, kRestorePatches)();
198
+ }
199
+ function getRawFetchHeaders(headers) {
200
+ if (!Reflect.has(headers, kRawHeaders)) return Array.from(headers.entries());
201
+ const rawHeaders = Reflect.get(headers, kRawHeaders);
202
+ return rawHeaders.length > 0 ? rawHeaders : Array.from(headers.entries());
203
+ }
204
+ /**
205
+ * Infers the raw headers from the given `HeadersInit` provided
206
+ * to the Request/Response constructor.
207
+ *
208
+ * If the `init.headers` is a Headers instance, use it directly.
209
+ * That means the headers were created standalone and already have
210
+ * the raw headers stored.
211
+ * If the `init.headers` is a HeadersInit, create a new Headers
212
+ * instance out of it.
213
+ */
214
+ function inferRawHeaders(headers) {
215
+ if (headers instanceof Headers) return Reflect.get(headers, kRawHeaders) || [];
216
+ return Reflect.get(new Headers(headers), kRawHeaders);
217
+ }
218
+
219
+ //#endregion
220
+ //#region src/interceptors/ClientRequest/utils/parserUtils.ts
221
+ /**
222
+ * @see https://github.com/nodejs/node/blob/f3adc11e37b8bfaaa026ea85c1cf22e3a0e29ae9/lib/_http_common.js#L180
223
+ */
224
+ function freeParser(parser, socket) {
225
+ if (parser._consumed) parser.unconsume();
226
+ parser._headers = [];
227
+ parser._url = "";
228
+ parser.socket = null;
229
+ parser.incoming = null;
230
+ parser.outgoing = null;
231
+ parser.maxHeaderPairs = 2e3;
232
+ parser._consumed = false;
233
+ parser.onIncoming = null;
234
+ parser[HTTPParser.kOnHeaders] = null;
235
+ parser[HTTPParser.kOnHeadersComplete] = null;
236
+ parser[HTTPParser.kOnMessageBegin] = null;
237
+ parser[HTTPParser.kOnMessageComplete] = null;
238
+ parser[HTTPParser.kOnBody] = null;
239
+ parser[HTTPParser.kOnExecute] = null;
240
+ parser[HTTPParser.kOnTimeout] = null;
241
+ parser.remove();
242
+ parser.free();
243
+ if (socket)
244
+ /**
245
+ * @note Unassigning the socket's parser will fail this assertion
246
+ * if there's still some data being processed on the socket:
247
+ * @see https://github.com/nodejs/node/blob/4e1f39b678b37017ac9baa0971e3aeecd3b67b51/lib/_http_client.js#L613
248
+ */
249
+ if (socket.destroyed) socket.parser = null;
250
+ else socket.once("end", () => {
251
+ socket.parser = null;
252
+ });
253
+ }
254
+
255
+ //#endregion
256
+ //#region src/interceptors/ClientRequest/MockHttpSocket.ts
257
+ const kRequestId = Symbol("kRequestId");
258
+ var MockHttpSocket = class extends MockSocket {
259
+ constructor(options) {
260
+ super({
261
+ write: (chunk, encoding, callback) => {
262
+ if (this.socketState !== "passthrough") this.writeBuffer.push([
263
+ chunk,
264
+ encoding,
265
+ callback
266
+ ]);
267
+ if (chunk) {
268
+ /**
269
+ * Forward any writes to the mock socket to the underlying original socket.
270
+ * This ensures functional duplex connections, like WebSocket.
271
+ * @see https://github.com/mswjs/interceptors/issues/682
272
+ */
273
+ if (this.socketState === "passthrough") this.originalSocket?.write(chunk, encoding, callback);
274
+ this.requestParser.execute(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, encoding));
275
+ }
276
+ },
277
+ read: (chunk) => {
278
+ if (chunk !== null)
279
+ /**
280
+ * @todo We need to free the parser if the connection has been
281
+ * upgraded to a non-HTTP protocol. It won't be able to parse data
282
+ * from that point onward anyway. No need to keep it in memory.
283
+ */
284
+ this.responseParser.execute(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
285
+ }
286
+ });
287
+ this.requestRawHeadersBuffer = [];
288
+ this.responseRawHeadersBuffer = [];
289
+ this.writeBuffer = [];
290
+ this.socketState = "unknown";
291
+ this.onRequestHeaders = (rawHeaders) => {
292
+ this.requestRawHeadersBuffer.push(...rawHeaders);
293
+ };
294
+ this.onRequestStart = (versionMajor, versionMinor, rawHeaders, _, path, __, ___, ____, shouldKeepAlive) => {
295
+ this.shouldKeepAlive = shouldKeepAlive;
296
+ const url = new URL(path || "", this.baseUrl);
297
+ const method = this.connectionOptions.method?.toUpperCase() || "GET";
298
+ const headers = FetchResponse.parseRawHeaders([...this.requestRawHeadersBuffer, ...rawHeaders || []]);
299
+ this.requestRawHeadersBuffer.length = 0;
300
+ const canHaveBody = method !== "GET" && method !== "HEAD";
301
+ if (url.username || url.password) {
302
+ if (!headers.has("authorization")) headers.set("authorization", `Basic ${url.username}:${url.password}`);
303
+ url.username = "";
304
+ url.password = "";
305
+ }
306
+ this.requestStream = new Readable({ read: () => {
307
+ this.flushWriteBuffer();
308
+ } });
309
+ const requestId = createRequestId();
310
+ this.request = new Request(url, {
311
+ method,
312
+ headers,
313
+ credentials: "same-origin",
314
+ duplex: canHaveBody ? "half" : void 0,
315
+ body: canHaveBody ? Readable.toWeb(this.requestStream) : null
316
+ });
317
+ Reflect.set(this.request, kRequestId, requestId);
318
+ setRawRequest(this.request, Reflect.get(this, "_httpMessage"));
319
+ setRawRequestBodyStream(this.request, this.requestStream);
320
+ /**
321
+ * @fixme Stop relying on the "X-Request-Id" request header
322
+ * to figure out if one interceptor has been invoked within another.
323
+ * @see https://github.com/mswjs/interceptors/issues/378
324
+ */
325
+ if (this.request.headers.has(INTERNAL_REQUEST_ID_HEADER_NAME)) {
326
+ this.passthrough();
327
+ return;
328
+ }
329
+ this.onRequest({
330
+ requestId,
331
+ request: this.request,
332
+ socket: this
333
+ });
334
+ };
335
+ this.onResponseHeaders = (rawHeaders) => {
336
+ this.responseRawHeadersBuffer.push(...rawHeaders);
337
+ };
338
+ this.onResponseStart = (versionMajor, versionMinor, rawHeaders, method, url, status, statusText) => {
339
+ const headers = FetchResponse.parseRawHeaders([...this.responseRawHeadersBuffer, ...rawHeaders || []]);
340
+ this.responseRawHeadersBuffer.length = 0;
341
+ const response = new FetchResponse(
342
+ /**
343
+ * @note The Fetch API response instance exposed to the consumer
344
+ * is created over the response stream of the HTTP parser. It is NOT
345
+ * related to the Socket instance. This way, you can read response body
346
+ * in response listener while the Socket instance delays the emission
347
+ * of "end" and other events until those response listeners are finished.
348
+ */
349
+ FetchResponse.isResponseWithBody(status) ? Readable.toWeb(this.responseStream = new Readable({ read() {} })) : null,
350
+ {
351
+ url,
352
+ status,
353
+ statusText,
354
+ headers
355
+ }
356
+ );
357
+ invariant(this.request, "Failed to handle a response: request does not exist");
358
+ FetchResponse.setUrl(this.request.url, response);
359
+ /**
360
+ * @fixme Stop relying on the "X-Request-Id" request header
361
+ * to figure out if one interceptor has been invoked within another.
362
+ * @see https://github.com/mswjs/interceptors/issues/378
363
+ */
364
+ if (this.request.headers.has(INTERNAL_REQUEST_ID_HEADER_NAME)) return;
365
+ this.responseListenersPromise = this.onResponse({
366
+ response,
367
+ isMockedResponse: this.socketState === "mock",
368
+ requestId: Reflect.get(this.request, kRequestId),
369
+ request: this.request,
370
+ socket: this
371
+ });
372
+ };
373
+ this.connectionOptions = options.connectionOptions;
374
+ this.createConnection = options.createConnection;
375
+ this.onRequest = options.onRequest;
376
+ this.onResponse = options.onResponse;
377
+ this.baseUrl = baseUrlFromConnectionOptions(this.connectionOptions);
378
+ this.requestParser = new HTTPParser();
379
+ this.requestParser.initialize(HTTPParser.REQUEST, {});
380
+ this.requestParser[HTTPParser.kOnHeaders] = this.onRequestHeaders.bind(this);
381
+ this.requestParser[HTTPParser.kOnHeadersComplete] = this.onRequestStart.bind(this);
382
+ this.requestParser[HTTPParser.kOnBody] = this.onRequestBody.bind(this);
383
+ this.requestParser[HTTPParser.kOnMessageComplete] = this.onRequestEnd.bind(this);
384
+ this.responseParser = new HTTPParser();
385
+ this.responseParser.initialize(HTTPParser.RESPONSE, {});
386
+ this.responseParser[HTTPParser.kOnHeaders] = this.onResponseHeaders.bind(this);
387
+ this.responseParser[HTTPParser.kOnHeadersComplete] = this.onResponseStart.bind(this);
388
+ this.responseParser[HTTPParser.kOnBody] = this.onResponseBody.bind(this);
389
+ this.responseParser[HTTPParser.kOnMessageComplete] = this.onResponseEnd.bind(this);
390
+ this.once("finish", () => freeParser(this.requestParser, this));
391
+ if (this.baseUrl.protocol === "https:") {
392
+ Reflect.set(this, "encrypted", true);
393
+ Reflect.set(this, "authorized", false);
394
+ Reflect.set(this, "getProtocol", () => "TLSv1.3");
395
+ Reflect.set(this, "getSession", () => void 0);
396
+ Reflect.set(this, "isSessionReused", () => false);
397
+ Reflect.set(this, "getCipher", () => ({
398
+ name: "AES256-SHA",
399
+ standardName: "TLS_RSA_WITH_AES_256_CBC_SHA",
400
+ version: "TLSv1.3"
401
+ }));
402
+ }
403
+ }
404
+ emit(event, ...args) {
405
+ const emitEvent = super.emit.bind(this, event, ...args);
406
+ if (this.responseListenersPromise) {
407
+ this.responseListenersPromise.finally(emitEvent);
408
+ return this.listenerCount(event) > 0;
409
+ }
410
+ return emitEvent();
411
+ }
412
+ destroy(error) {
413
+ freeParser(this.responseParser, this);
414
+ if (error) this.emit("error", error);
415
+ return super.destroy(error);
416
+ }
417
+ /**
418
+ * Establish this Socket connection as-is and pipe
419
+ * its data/events through this Socket.
420
+ */
421
+ passthrough() {
422
+ this.socketState = "passthrough";
423
+ if (this.destroyed) return;
424
+ const socket = this.createConnection();
425
+ this.originalSocket = socket;
426
+ /**
427
+ * @note Inherit the original socket's connection handle.
428
+ * Without this, each push to the mock socket results in a
429
+ * new "connection" listener being added (i.e. buffering pushes).
430
+ * @see https://github.com/nodejs/node/blob/b18153598b25485ce4f54d0c5cb830a9457691ee/lib/net.js#L734
431
+ */
432
+ if ("_handle" in socket) Object.defineProperty(this, "_handle", {
433
+ value: socket._handle,
434
+ enumerable: true,
435
+ writable: true
436
+ });
437
+ this.once("close", () => {
438
+ socket.removeAllListeners();
439
+ if (!socket.destroyed) socket.destroy();
440
+ this.originalSocket = void 0;
441
+ });
442
+ this.address = socket.address.bind(socket);
443
+ let writeArgs;
444
+ let headersWritten = false;
445
+ while (writeArgs = this.writeBuffer.shift()) if (writeArgs !== void 0) {
446
+ if (!headersWritten) {
447
+ const [chunk, encoding, callback] = writeArgs;
448
+ const chunkString = chunk.toString();
449
+ const chunkBeforeRequestHeaders = chunkString.slice(0, chunkString.indexOf("\r\n") + 2);
450
+ const chunkAfterRequestHeaders = chunkString.slice(chunk.indexOf("\r\n\r\n"));
451
+ const headersChunk = `${chunkBeforeRequestHeaders}${getRawFetchHeaders(this.request.headers).filter(([name]) => {
452
+ return name.toLowerCase() !== INTERNAL_REQUEST_ID_HEADER_NAME;
453
+ }).map(([name, value]) => `${name}: ${value}`).join("\r\n")}${chunkAfterRequestHeaders}`;
454
+ socket.write(headersChunk, encoding, callback);
455
+ headersWritten = true;
456
+ continue;
457
+ }
458
+ socket.write(...writeArgs);
459
+ }
460
+ if (Reflect.get(socket, "encrypted")) [
461
+ "encrypted",
462
+ "authorized",
463
+ "getProtocol",
464
+ "getSession",
465
+ "isSessionReused",
466
+ "getCipher"
467
+ ].forEach((propertyName) => {
468
+ Object.defineProperty(this, propertyName, {
469
+ enumerable: true,
470
+ get: () => {
471
+ const value = Reflect.get(socket, propertyName);
472
+ return typeof value === "function" ? value.bind(socket) : value;
473
+ }
474
+ });
475
+ });
476
+ socket.on("lookup", (...args) => this.emit("lookup", ...args)).on("connect", () => {
477
+ this.connecting = socket.connecting;
478
+ this.emit("connect");
479
+ }).on("secureConnect", () => this.emit("secureConnect")).on("secure", () => this.emit("secure")).on("session", (session) => this.emit("session", session)).on("ready", () => this.emit("ready")).on("drain", () => this.emit("drain")).on("data", (chunk) => {
480
+ this.push(chunk);
481
+ }).on("error", (error) => {
482
+ Reflect.set(this, "_hadError", Reflect.get(socket, "_hadError"));
483
+ this.emit("error", error);
484
+ }).on("resume", () => this.emit("resume")).on("timeout", () => this.emit("timeout")).on("prefinish", () => this.emit("prefinish")).on("finish", () => this.emit("finish")).on("close", (hadError) => this.emit("close", hadError)).on("end", () => this.emit("end"));
485
+ }
486
+ /**
487
+ * Convert the given Fetch API `Response` instance to an
488
+ * HTTP message and push it to the socket.
489
+ */
490
+ async respondWith(response) {
491
+ if (this.destroyed) return;
492
+ invariant(this.socketState !== "mock", "[MockHttpSocket] Failed to respond to the \"%s %s\" request with \"%s %s\": the request has already been handled", this.request?.method, this.request?.url, response.status, response.statusText);
493
+ if (isPropertyAccessible(response, "type") && response.type === "error") {
494
+ this.errorWith(/* @__PURE__ */ new TypeError("Network error"));
495
+ return;
496
+ }
497
+ this.mockConnect();
498
+ this.socketState = "mock";
499
+ this.flushWriteBuffer();
500
+ const serverResponse = new ServerResponse(new IncomingMessage(this));
501
+ /**
502
+ * Assign a mock socket instance to the server response to
503
+ * spy on the response chunk writes. Push the transformed response chunks
504
+ * to this `MockHttpSocket` instance to trigger the "data" event.
505
+ * @note Providing the same `MockSocket` instance when creating `ServerResponse`
506
+ * does not have the same effect.
507
+ * @see https://github.com/nodejs/node/blob/10099bb3f7fd97bb9dd9667188426866b3098e07/test/parallel/test-http-server-response-standalone.js#L32
508
+ */
509
+ serverResponse.assignSocket(new MockSocket({
510
+ write: (chunk, encoding, callback) => {
511
+ this.push(chunk, encoding);
512
+ callback?.();
513
+ },
514
+ read() {}
515
+ }));
516
+ /**
517
+ * @note Remove the `Connection` and `Date` response headers
518
+ * injected by `ServerResponse` by default. Those are required
519
+ * from the server but the interceptor is NOT technically a server.
520
+ * It's confusing to add response headers that the developer didn't
521
+ * specify themselves. They can always add these if they wish.
522
+ * @see https://www.rfc-editor.org/rfc/rfc9110#field.date
523
+ * @see https://www.rfc-editor.org/rfc/rfc9110#field.connection
524
+ */
525
+ serverResponse.removeHeader("connection");
526
+ serverResponse.removeHeader("date");
527
+ const rawResponseHeaders = getRawFetchHeaders(response.headers);
528
+ /**
529
+ * @note Call `.writeHead` in order to set the raw response headers
530
+ * in the same case as they were provided by the developer. Using
531
+ * `.setHeader()`/`.appendHeader()` normalizes header names.
532
+ */
533
+ serverResponse.writeHead(response.status, response.statusText || STATUS_CODES[response.status], rawResponseHeaders);
534
+ this.once("error", () => {
535
+ serverResponse.destroy();
536
+ });
537
+ if (response.body) try {
538
+ const reader = response.body.getReader();
539
+ while (true) {
540
+ const { done, value } = await reader.read();
541
+ if (done) {
542
+ serverResponse.end();
543
+ break;
544
+ }
545
+ serverResponse.write(value);
546
+ }
547
+ } catch (error) {
548
+ if (error instanceof Error) {
549
+ serverResponse.destroy();
550
+ /**
551
+ * @note Destroy the request socket gracefully.
552
+ * Response stream errors do NOT produce request errors.
553
+ */
554
+ this.destroy();
555
+ return;
556
+ }
557
+ serverResponse.destroy();
558
+ throw error;
559
+ }
560
+ else serverResponse.end();
561
+ if (!this.shouldKeepAlive) {
562
+ this.emit("readable");
563
+ /**
564
+ * @todo @fixme This is likely a hack.
565
+ * Since we push null to the socket, it never propagates to the
566
+ * parser, and the parser never calls "onResponseEnd" to close
567
+ * the response stream. We are closing the stream here manually
568
+ * but that shouldn't be the case.
569
+ */
570
+ this.responseStream?.push(null);
571
+ this.push(null);
572
+ }
573
+ }
574
+ /**
575
+ * Close this socket connection with the given error.
576
+ */
577
+ errorWith(error) {
578
+ this.destroy(error);
579
+ }
580
+ mockConnect() {
581
+ this.connecting = false;
582
+ const isIPv6 = net.isIPv6(this.connectionOptions.hostname) || this.connectionOptions.family === 6;
583
+ const addressInfo = {
584
+ address: isIPv6 ? "::1" : "127.0.0.1",
585
+ family: isIPv6 ? "IPv6" : "IPv4",
586
+ port: this.connectionOptions.port
587
+ };
588
+ this.address = () => addressInfo;
589
+ this.emit("lookup", null, addressInfo.address, addressInfo.family === "IPv6" ? 6 : 4, this.connectionOptions.host);
590
+ this.emit("connect");
591
+ this.emit("ready");
592
+ if (this.baseUrl.protocol === "https:") {
593
+ this.emit("secure");
594
+ this.emit("secureConnect");
595
+ this.emit("session", this.connectionOptions.session || Buffer.from("mock-session-renegotiate"));
596
+ this.emit("session", Buffer.from("mock-session-resume"));
597
+ }
598
+ }
599
+ flushWriteBuffer() {
600
+ for (const writeCall of this.writeBuffer) if (typeof writeCall[2] === "function") {
601
+ writeCall[2]();
602
+ /**
603
+ * @note Remove the callback from the write call
604
+ * so it doesn't get called twice on passthrough
605
+ * if `request.end()` was called within `request.write()`.
606
+ * @see https://github.com/mswjs/interceptors/issues/684
607
+ */
608
+ writeCall[2] = void 0;
609
+ }
610
+ }
611
+ onRequestBody(chunk) {
612
+ invariant(this.requestStream, "Failed to write to a request stream: stream does not exist");
613
+ this.requestStream.push(chunk);
614
+ }
615
+ onRequestEnd() {
616
+ if (this.requestStream) this.requestStream.push(null);
617
+ }
618
+ onResponseBody(chunk) {
619
+ invariant(this.responseStream, "Failed to write to a response stream: stream does not exist");
620
+ this.responseStream.push(chunk);
621
+ }
622
+ onResponseEnd() {
623
+ if (this.responseStream) this.responseStream.push(null);
624
+ }
625
+ };
626
+
627
+ //#endregion
628
+ //#region src/interceptors/ClientRequest/agents.ts
629
+ var MockAgent = class extends http.Agent {
630
+ constructor(options) {
631
+ super();
632
+ this.customAgent = options.customAgent;
633
+ this.onRequest = options.onRequest;
634
+ this.onResponse = options.onResponse;
635
+ }
636
+ createConnection(options, callback) {
637
+ const createConnection = this.customAgent instanceof http.Agent ? this.customAgent.createConnection : super.createConnection;
638
+ const createConnectionOptions = this.customAgent instanceof http.Agent ? {
639
+ ...options,
640
+ ...this.customAgent.options
641
+ } : options;
642
+ return new MockHttpSocket({
643
+ connectionOptions: options,
644
+ createConnection: createConnection.bind(this.customAgent || this, createConnectionOptions, callback),
645
+ onRequest: this.onRequest.bind(this),
646
+ onResponse: this.onResponse.bind(this)
647
+ });
648
+ }
649
+ };
650
+ var MockHttpsAgent = class extends https.Agent {
651
+ constructor(options) {
652
+ super();
653
+ this.customAgent = options.customAgent;
654
+ this.onRequest = options.onRequest;
655
+ this.onResponse = options.onResponse;
656
+ }
657
+ createConnection(options, callback) {
658
+ const createConnection = this.customAgent instanceof http.Agent ? this.customAgent.createConnection : super.createConnection;
659
+ const createConnectionOptions = this.customAgent instanceof http.Agent ? {
660
+ ...options,
661
+ ...this.customAgent.options
662
+ } : options;
663
+ return new MockHttpSocket({
664
+ connectionOptions: options,
665
+ createConnection: createConnection.bind(this.customAgent || this, createConnectionOptions, callback),
666
+ onRequest: this.onRequest.bind(this),
667
+ onResponse: this.onResponse.bind(this)
668
+ });
669
+ }
670
+ };
671
+
672
+ //#endregion
673
+ //#region src/utils/getUrlByRequestOptions.ts
674
+ const logger$2 = new Logger("utils getUrlByRequestOptions");
675
+ const DEFAULT_PATH = "/";
676
+ const DEFAULT_PROTOCOL = "http:";
677
+ const DEFAULT_HOSTNAME = "localhost";
678
+ const SSL_PORT = 443;
679
+ function getAgent(options) {
680
+ return options.agent instanceof Agent ? options.agent : void 0;
681
+ }
682
+ function getProtocolByRequestOptions(options) {
683
+ if (options.protocol) return options.protocol;
684
+ const agentProtocol = getAgent(options)?.protocol;
685
+ if (agentProtocol) return agentProtocol;
686
+ const port = getPortByRequestOptions(options);
687
+ return options.cert || port === SSL_PORT ? "https:" : options.uri?.protocol || DEFAULT_PROTOCOL;
688
+ }
689
+ function getPortByRequestOptions(options) {
690
+ if (options.port) return Number(options.port);
691
+ const agent = getAgent(options);
692
+ if (agent?.options.port) return Number(agent.options.port);
693
+ if (agent?.defaultPort) return Number(agent.defaultPort);
694
+ }
695
+ function getAuthByRequestOptions(options) {
696
+ if (options.auth) {
697
+ const [username, password] = options.auth.split(":");
698
+ return {
699
+ username,
700
+ password
701
+ };
702
+ }
703
+ }
704
+ /**
705
+ * Returns true if host looks like an IPv6 address without surrounding brackets
706
+ * It assumes any host containing `:` is definitely not IPv4 and probably IPv6,
707
+ * but note that this could include invalid IPv6 addresses as well.
708
+ */
709
+ function isRawIPv6Address(host) {
710
+ return host.includes(":") && !host.startsWith("[") && !host.endsWith("]");
711
+ }
712
+ function getHostname(options) {
713
+ let host = options.hostname || options.host;
714
+ if (host) {
715
+ if (isRawIPv6Address(host)) host = `[${host}]`;
716
+ return new URL(`http://${host}`).hostname;
717
+ }
718
+ return DEFAULT_HOSTNAME;
719
+ }
720
+ /**
721
+ * Creates a `URL` instance from a given `RequestOptions` object.
722
+ */
723
+ function getUrlByRequestOptions(options) {
724
+ logger$2.info("request options", options);
725
+ if (options.uri) {
726
+ logger$2.info("constructing url from explicitly provided \"options.uri\": %s", options.uri);
727
+ return new URL(options.uri.href);
728
+ }
729
+ logger$2.info("figuring out url from request options...");
730
+ const protocol = getProtocolByRequestOptions(options);
731
+ logger$2.info("protocol", protocol);
732
+ const port = getPortByRequestOptions(options);
733
+ logger$2.info("port", port);
734
+ const hostname = getHostname(options);
735
+ logger$2.info("hostname", hostname);
736
+ const path = options.path || DEFAULT_PATH;
737
+ logger$2.info("path", path);
738
+ const credentials = getAuthByRequestOptions(options);
739
+ logger$2.info("credentials", credentials);
740
+ const authString = credentials ? `${credentials.username}:${credentials.password}@` : "";
741
+ logger$2.info("auth string:", authString);
742
+ const portString = typeof port !== "undefined" ? `:${port}` : "";
743
+ const url = new URL(`${protocol}//${hostname}${portString}${path}`);
744
+ url.username = credentials?.username || "";
745
+ url.password = credentials?.password || "";
746
+ logger$2.info("created url:", url);
747
+ return url;
748
+ }
749
+
750
+ //#endregion
751
+ //#region src/utils/cloneObject.ts
752
+ const logger$1 = new Logger("cloneObject");
753
+ function isPlainObject(obj) {
754
+ logger$1.info("is plain object?", obj);
755
+ if (obj == null || !obj.constructor?.name) {
756
+ logger$1.info("given object is undefined, not a plain object...");
757
+ return false;
758
+ }
759
+ logger$1.info("checking the object constructor:", obj.constructor.name);
760
+ return obj.constructor.name === "Object";
761
+ }
762
+ function cloneObject(obj) {
763
+ logger$1.info("cloning object:", obj);
764
+ const enumerableProperties = Object.entries(obj).reduce((acc, [key, value]) => {
765
+ logger$1.info("analyzing key-value pair:", key, value);
766
+ acc[key] = isPlainObject(value) ? cloneObject(value) : value;
767
+ return acc;
768
+ }, {});
769
+ return isPlainObject(obj) ? enumerableProperties : Object.assign(Object.getPrototypeOf(obj), enumerableProperties);
770
+ }
771
+
772
+ //#endregion
773
+ //#region src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts
774
+ const logger = new Logger("http normalizeClientRequestArgs");
775
+ function resolveRequestOptions(args, url) {
776
+ if (typeof args[1] === "undefined" || typeof args[1] === "function") {
777
+ logger.info("request options not provided, deriving from the url", url);
778
+ return urlToHttpOptions(url);
779
+ }
780
+ if (args[1]) {
781
+ logger.info("has custom RequestOptions!", args[1]);
782
+ const requestOptionsFromUrl = urlToHttpOptions(url);
783
+ logger.info("derived RequestOptions from the URL:", requestOptionsFromUrl);
784
+ /**
785
+ * Clone the request options to lock their state
786
+ * at the moment they are provided to `ClientRequest`.
787
+ * @see https://github.com/mswjs/interceptors/issues/86
788
+ */
789
+ logger.info("cloning RequestOptions...");
790
+ const clonedRequestOptions = cloneObject(args[1]);
791
+ logger.info("successfully cloned RequestOptions!", clonedRequestOptions);
792
+ return {
793
+ ...requestOptionsFromUrl,
794
+ ...clonedRequestOptions
795
+ };
796
+ }
797
+ logger.info("using an empty object as request options");
798
+ return {};
799
+ }
800
+ /**
801
+ * Overrides the given `URL` instance with the explicit properties provided
802
+ * on the `RequestOptions` object. The options object takes precedence,
803
+ * and will replace URL properties like "host", "path", and "port", if specified.
804
+ */
805
+ function overrideUrlByRequestOptions(url, options) {
806
+ url.host = options.host || url.host;
807
+ url.hostname = options.hostname || url.hostname;
808
+ url.port = options.port ? options.port.toString() : url.port;
809
+ if (options.path) {
810
+ const parsedOptionsPath = parse(options.path, false);
811
+ url.pathname = parsedOptionsPath.pathname || "";
812
+ url.search = parsedOptionsPath.search || "";
813
+ }
814
+ return url;
815
+ }
816
+ function resolveCallback(args) {
817
+ return typeof args[1] === "function" ? args[1] : args[2];
818
+ }
819
+ /**
820
+ * Normalizes parameters given to a `http.request` call
821
+ * so it always has a `URL` and `RequestOptions`.
822
+ */
823
+ function normalizeClientRequestArgs(defaultProtocol, args) {
824
+ let url;
825
+ let options;
826
+ let callback;
827
+ logger.info("arguments", args);
828
+ logger.info("using default protocol:", defaultProtocol);
829
+ if (args.length === 0) {
830
+ const url$1 = new URL$1("http://localhost");
831
+ return [url$1, resolveRequestOptions(args, url$1)];
832
+ }
833
+ if (typeof args[0] === "string") {
834
+ logger.info("first argument is a location string:", args[0]);
835
+ url = new URL$1(args[0]);
836
+ logger.info("created a url:", url);
837
+ const requestOptionsFromUrl = urlToHttpOptions(url);
838
+ logger.info("request options from url:", requestOptionsFromUrl);
839
+ options = resolveRequestOptions(args, url);
840
+ logger.info("resolved request options:", options);
841
+ callback = resolveCallback(args);
842
+ } else if (args[0] instanceof URL$1) {
843
+ url = args[0];
844
+ logger.info("first argument is a URL:", url);
845
+ if (typeof args[1] !== "undefined" && isObject(args[1])) url = overrideUrlByRequestOptions(url, args[1]);
846
+ options = resolveRequestOptions(args, url);
847
+ logger.info("derived request options:", options);
848
+ callback = resolveCallback(args);
849
+ } else if ("hash" in args[0] && !("method" in args[0])) {
850
+ const [legacyUrl] = args;
851
+ logger.info("first argument is a legacy URL:", legacyUrl);
852
+ if (legacyUrl.hostname === null) {
853
+ /**
854
+ * We are dealing with a relative url, so use the path as an "option" and
855
+ * merge in any existing options, giving priority to existing options -- i.e. a path in any
856
+ * existing options will take precedence over the one contained in the url. This is consistent
857
+ * with the behaviour in ClientRequest.
858
+ * @see https://github.com/nodejs/node/blob/d84f1312915fe45fe0febe888db692c74894c382/lib/_http_client.js#L122
859
+ */
860
+ logger.info("given legacy URL is relative (no hostname)");
861
+ return isObject(args[1]) ? normalizeClientRequestArgs(defaultProtocol, [{
862
+ path: legacyUrl.path,
863
+ ...args[1]
864
+ }, args[2]]) : normalizeClientRequestArgs(defaultProtocol, [{ path: legacyUrl.path }, args[1]]);
865
+ }
866
+ logger.info("given legacy url is absolute");
867
+ const resolvedUrl = new URL$1(legacyUrl.href);
868
+ return args[1] === void 0 ? normalizeClientRequestArgs(defaultProtocol, [resolvedUrl]) : typeof args[1] === "function" ? normalizeClientRequestArgs(defaultProtocol, [resolvedUrl, args[1]]) : normalizeClientRequestArgs(defaultProtocol, [
869
+ resolvedUrl,
870
+ args[1],
871
+ args[2]
872
+ ]);
873
+ } else if (isObject(args[0])) {
874
+ options = { ...args[0] };
875
+ logger.info("first argument is RequestOptions:", options);
876
+ options.protocol = options.protocol || defaultProtocol;
877
+ logger.info("normalized request options:", options);
878
+ url = getUrlByRequestOptions(options);
879
+ logger.info("created a URL from RequestOptions:", url.href);
880
+ callback = resolveCallback(args);
881
+ } else throw new Error(`Failed to construct ClientRequest with these parameters: ${args}`);
882
+ options.protocol = options.protocol || url.protocol;
883
+ options.method = options.method || "GET";
884
+ /**
885
+ * Ensure that the default Agent is always set.
886
+ * This prevents the protocol mismatch for requests with { agent: false },
887
+ * where the global Agent is inferred.
888
+ * @see https://github.com/mswjs/msw/issues/1150
889
+ * @see https://github.com/nodejs/node/blob/418ff70b810f0e7112d48baaa72932a56cfa213b/lib/_http_client.js#L130
890
+ * @see https://github.com/nodejs/node/blob/418ff70b810f0e7112d48baaa72932a56cfa213b/lib/_http_client.js#L157-L159
891
+ */
892
+ if (!options._defaultAgent) {
893
+ logger.info("has no default agent, setting the default agent for \"%s\"", options.protocol);
894
+ options._defaultAgent = options.protocol === "https:" ? globalAgent$1 : globalAgent;
895
+ }
896
+ logger.info("successfully resolved url:", url.href);
897
+ logger.info("successfully resolved options:", options);
898
+ logger.info("successfully resolved callback:", callback);
899
+ /**
900
+ * @note If the user-provided URL is not a valid URL in Node.js,
901
+ * (e.g. the one provided by the JSDOM polyfills), case it to
902
+ * string. Otherwise, this throws on Node.js incompatibility
903
+ * (`ERR_INVALID_ARG_TYPE` on the connection listener)
904
+ * @see https://github.com/node-fetch/node-fetch/issues/1376#issuecomment-966435555
905
+ */
906
+ if (!(url instanceof URL$1)) url = url.toString();
907
+ return [
908
+ url,
909
+ options,
910
+ callback
911
+ ];
912
+ }
913
+
914
+ //#endregion
915
+ //#region src/interceptors/ClientRequest/index.ts
916
+ var ClientRequestInterceptor = class ClientRequestInterceptor extends Interceptor {
917
+ static {
918
+ this.symbol = Symbol("client-request-interceptor");
919
+ }
920
+ constructor() {
921
+ super(ClientRequestInterceptor.symbol);
922
+ this.onRequest = async ({ request, socket }) => {
923
+ const controller = new RequestController(request, {
924
+ passthrough() {
925
+ socket.passthrough();
926
+ },
927
+ async respondWith(response) {
928
+ await socket.respondWith(response);
929
+ },
930
+ errorWith(reason) {
931
+ if (reason instanceof Error) socket.errorWith(reason);
932
+ }
933
+ });
934
+ await handleRequest({
935
+ request,
936
+ requestId: Reflect.get(request, kRequestId),
937
+ controller,
938
+ emitter: this.emitter
939
+ });
940
+ };
941
+ this.onResponse = async ({ requestId, request, response, isMockedResponse }) => {
942
+ return emitAsync(this.emitter, "response", {
943
+ requestId,
944
+ request,
945
+ response,
946
+ isMockedResponse
947
+ });
948
+ };
949
+ }
950
+ setup() {
951
+ const { ClientRequest: OriginalClientRequest, get: originalGet, request: originalRequest } = http;
952
+ const { get: originalHttpsGet, request: originalHttpsRequest } = https;
953
+ const onRequest = this.onRequest.bind(this);
954
+ const onResponse = this.onResponse.bind(this);
955
+ http.ClientRequest = new Proxy(http.ClientRequest, { construct: (target, args) => {
956
+ const [url, options, callback] = normalizeClientRequestArgs("http:", args);
957
+ options.agent = new (options.protocol === "https:" ? MockHttpsAgent : MockAgent)({
958
+ customAgent: options.agent,
959
+ onRequest,
960
+ onResponse
961
+ });
962
+ return Reflect.construct(target, [
963
+ url,
964
+ options,
965
+ callback
966
+ ]);
967
+ } });
968
+ http.request = new Proxy(http.request, { apply: (target, thisArg, args) => {
969
+ const [url, options, callback] = normalizeClientRequestArgs("http:", args);
970
+ options.agent = new MockAgent({
971
+ customAgent: options.agent,
972
+ onRequest,
973
+ onResponse
974
+ });
975
+ return Reflect.apply(target, thisArg, [
976
+ url,
977
+ options,
978
+ callback
979
+ ]);
980
+ } });
981
+ http.get = new Proxy(http.get, { apply: (target, thisArg, args) => {
982
+ const [url, options, callback] = normalizeClientRequestArgs("http:", args);
983
+ options.agent = new MockAgent({
984
+ customAgent: options.agent,
985
+ onRequest,
986
+ onResponse
987
+ });
988
+ return Reflect.apply(target, thisArg, [
989
+ url,
990
+ options,
991
+ callback
992
+ ]);
993
+ } });
994
+ https.request = new Proxy(https.request, { apply: (target, thisArg, args) => {
995
+ const [url, options, callback] = normalizeClientRequestArgs("https:", args);
996
+ options.agent = new MockHttpsAgent({
997
+ customAgent: options.agent,
998
+ onRequest,
999
+ onResponse
1000
+ });
1001
+ return Reflect.apply(target, thisArg, [
1002
+ url,
1003
+ options,
1004
+ callback
1005
+ ]);
1006
+ } });
1007
+ https.get = new Proxy(https.get, { apply: (target, thisArg, args) => {
1008
+ const [url, options, callback] = normalizeClientRequestArgs("https:", args);
1009
+ options.agent = new MockHttpsAgent({
1010
+ customAgent: options.agent,
1011
+ onRequest,
1012
+ onResponse
1013
+ });
1014
+ return Reflect.apply(target, thisArg, [
1015
+ url,
1016
+ options,
1017
+ callback
1018
+ ]);
1019
+ } });
1020
+ recordRawFetchHeaders();
1021
+ this.subscriptions.push(() => {
1022
+ http.ClientRequest = OriginalClientRequest;
1023
+ http.get = originalGet;
1024
+ http.request = originalRequest;
1025
+ https.get = originalHttpsGet;
1026
+ https.request = originalHttpsRequest;
1027
+ restoreHeadersPrototype();
1028
+ });
1029
+ }
1030
+ };
1031
+
1032
+ //#endregion
1033
+ export { ClientRequestInterceptor as t };
1034
+ //# sourceMappingURL=ClientRequest-Ca8Qykuv.mjs.map