@mswjs/interceptors 0.12.6 → 0.13.2

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 (100) hide show
  1. package/README.md +64 -15
  2. package/lib/createInterceptor.d.ts +7 -0
  3. package/lib/createInterceptor.js.map +1 -1
  4. package/lib/interceptors/ClientRequest/NodeClientRequest.d.ts +38 -0
  5. package/lib/interceptors/ClientRequest/NodeClientRequest.js +420 -0
  6. package/lib/interceptors/ClientRequest/NodeClientRequest.js.map +1 -0
  7. package/lib/interceptors/ClientRequest/http.get.d.ts +5 -0
  8. package/lib/interceptors/ClientRequest/http.get.js +47 -0
  9. package/lib/interceptors/ClientRequest/http.get.js.map +1 -0
  10. package/lib/interceptors/ClientRequest/http.request.d.ts +5 -0
  11. package/lib/interceptors/ClientRequest/http.request.js +44 -0
  12. package/lib/interceptors/ClientRequest/http.request.js.map +1 -0
  13. package/lib/interceptors/ClientRequest/index.d.ts +5 -1
  14. package/lib/interceptors/ClientRequest/index.js +50 -84
  15. package/lib/interceptors/ClientRequest/index.js.map +1 -1
  16. package/lib/interceptors/ClientRequest/utils/cloneIncomingMessage.d.ts +7 -0
  17. package/lib/interceptors/ClientRequest/utils/cloneIncomingMessage.js +77 -0
  18. package/lib/interceptors/ClientRequest/utils/cloneIncomingMessage.js.map +1 -0
  19. package/lib/interceptors/ClientRequest/utils/getIncomingMessageBody.d.ts +1 -1
  20. package/lib/interceptors/ClientRequest/utils/getIncomingMessageBody.js +21 -12
  21. package/lib/interceptors/ClientRequest/utils/getIncomingMessageBody.js.map +1 -1
  22. package/lib/interceptors/ClientRequest/utils/normalizeClientRequestArgs.d.ts +17 -0
  23. package/lib/interceptors/ClientRequest/utils/{normalizeHttpRequestParams.js → normalizeClientRequestArgs.js} +65 -39
  24. package/lib/interceptors/ClientRequest/utils/normalizeClientRequestArgs.js.map +1 -0
  25. package/lib/interceptors/ClientRequest/utils/normalizeClientRequestEndArgs.d.ts +15 -0
  26. package/lib/interceptors/ClientRequest/utils/{normalizeHttpRequestEndParams.js → normalizeClientRequestEndArgs.js} +5 -6
  27. package/lib/interceptors/ClientRequest/utils/normalizeClientRequestEndArgs.js.map +1 -0
  28. package/lib/interceptors/ClientRequest/utils/normalizeClientRequestWriteArgs.d.ts +13 -0
  29. package/lib/interceptors/ClientRequest/utils/normalizeClientRequestWriteArgs.js +20 -0
  30. package/lib/interceptors/ClientRequest/utils/normalizeClientRequestWriteArgs.js.map +1 -0
  31. package/lib/interceptors/XMLHttpRequest/XMLHttpRequestOverride.js +3 -2
  32. package/lib/interceptors/XMLHttpRequest/XMLHttpRequestOverride.js.map +1 -1
  33. package/lib/interceptors/fetch/index.js +6 -4
  34. package/lib/interceptors/fetch/index.js.map +1 -1
  35. package/lib/utils/getUrlByRequestOptions.d.ts +5 -4
  36. package/lib/utils/getUrlByRequestOptions.js.map +1 -1
  37. package/package.json +33 -18
  38. package/src/createInterceptor.ts +100 -0
  39. package/src/index.ts +5 -0
  40. package/src/interceptors/ClientRequest/NodeClientRequest.test.ts +283 -0
  41. package/src/interceptors/ClientRequest/NodeClientRequest.ts +377 -0
  42. package/src/interceptors/ClientRequest/http.get.ts +32 -0
  43. package/src/interceptors/ClientRequest/http.request.ts +29 -0
  44. package/src/interceptors/ClientRequest/index.ts +61 -0
  45. package/src/interceptors/ClientRequest/utils/bodyBufferToString.test.ts +16 -0
  46. package/src/interceptors/ClientRequest/utils/bodyBufferToString.ts +7 -0
  47. package/src/interceptors/ClientRequest/utils/cloneIncomingMessage.test.ts +20 -0
  48. package/src/interceptors/ClientRequest/utils/cloneIncomingMessage.ts +41 -0
  49. package/src/interceptors/ClientRequest/utils/concatChunkToBuffer.test.ts +13 -0
  50. package/src/interceptors/ClientRequest/utils/concatChunkToBuffer.ts +10 -0
  51. package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.test.ts +44 -0
  52. package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.ts +38 -0
  53. package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.test.ts +336 -0
  54. package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts +205 -0
  55. package/src/interceptors/ClientRequest/utils/normalizeClientRequestEndArgs.test.ts +40 -0
  56. package/src/interceptors/ClientRequest/utils/normalizeClientRequestEndArgs.ts +51 -0
  57. package/src/interceptors/ClientRequest/utils/normalizeClientRequestWriteArgs.test.ts +35 -0
  58. package/src/interceptors/ClientRequest/utils/normalizeClientRequestWriteArgs.ts +36 -0
  59. package/src/interceptors/XMLHttpRequest/XMLHttpRequestOverride.ts +565 -0
  60. package/src/interceptors/XMLHttpRequest/index.ts +34 -0
  61. package/src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts +51 -0
  62. package/src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts +17 -0
  63. package/src/interceptors/XMLHttpRequest/utils/bufferFrom.test.ts +11 -0
  64. package/src/interceptors/XMLHttpRequest/utils/bufferFrom.ts +16 -0
  65. package/src/interceptors/XMLHttpRequest/utils/createEvent.test.ts +27 -0
  66. package/src/interceptors/XMLHttpRequest/utils/createEvent.ts +41 -0
  67. package/src/interceptors/fetch/index.ts +89 -0
  68. package/src/presets/browser.ts +8 -0
  69. package/src/presets/node.ts +8 -0
  70. package/src/remote.ts +176 -0
  71. package/src/utils/cloneObject.test.ts +93 -0
  72. package/src/utils/cloneObject.ts +34 -0
  73. package/src/utils/getCleanUrl.test.ts +31 -0
  74. package/src/utils/getCleanUrl.ts +6 -0
  75. package/src/utils/getRequestOptionsByUrl.ts +29 -0
  76. package/src/utils/getUrlByRequestOptions.test.ts +140 -0
  77. package/src/utils/getUrlByRequestOptions.ts +108 -0
  78. package/src/utils/isObject.test.ts +19 -0
  79. package/src/utils/isObject.ts +6 -0
  80. package/src/utils/parseJson.test.ts +9 -0
  81. package/src/utils/parseJson.ts +12 -0
  82. package/src/utils/toIsoResponse.test.ts +39 -0
  83. package/src/utils/toIsoResponse.ts +14 -0
  84. package/src/utils/uuid.ts +7 -0
  85. package/lib/interceptors/ClientRequest/ClientRequest.glossary.d.ts +0 -6
  86. package/lib/interceptors/ClientRequest/ClientRequest.glossary.js +0 -3
  87. package/lib/interceptors/ClientRequest/ClientRequest.glossary.js.map +0 -1
  88. package/lib/interceptors/ClientRequest/createClientRequestOverride.d.ts +0 -12
  89. package/lib/interceptors/ClientRequest/createClientRequestOverride.js +0 -340
  90. package/lib/interceptors/ClientRequest/createClientRequestOverride.js.map +0 -1
  91. package/lib/interceptors/ClientRequest/polyfills/SocketPolyfill.d.ts +0 -49
  92. package/lib/interceptors/ClientRequest/polyfills/SocketPolyfill.js +0 -118
  93. package/lib/interceptors/ClientRequest/polyfills/SocketPolyfill.js.map +0 -1
  94. package/lib/interceptors/ClientRequest/utils/inheritRequestHeaders.d.ts +0 -3
  95. package/lib/interceptors/ClientRequest/utils/inheritRequestHeaders.js +0 -34
  96. package/lib/interceptors/ClientRequest/utils/inheritRequestHeaders.js.map +0 -1
  97. package/lib/interceptors/ClientRequest/utils/normalizeHttpRequestEndParams.d.ts +0 -17
  98. package/lib/interceptors/ClientRequest/utils/normalizeHttpRequestEndParams.js.map +0 -1
  99. package/lib/interceptors/ClientRequest/utils/normalizeHttpRequestParams.d.ts +0 -11
  100. package/lib/interceptors/ClientRequest/utils/normalizeHttpRequestParams.js.map +0 -1
package/README.md CHANGED
@@ -1,5 +1,4 @@
1
1
  [![Latest version](https://img.shields.io/npm/v/@mswjs/interceptors.svg)](https://www.npmjs.com/package/@mswjs/interceptors)
2
- [![Build status](https://img.shields.io/circleci/project/github/mswjs/interceptors/master.svg)](https://app.circleci.com/pipelines/github/mswjs/interceptors)
3
2
 
4
3
  # `@mswjs/interceptors`
5
4
 
@@ -11,7 +10,7 @@ Low-level HTTP/HTTPS/XHR/fetch request interception library.
11
10
  - `https.get`/`https.request`
12
11
  - `XMLHttpRequest`
13
12
  - `fetch`
14
- - Any third-party libraries that use the modules above (i.e. `request`, `node-fetch`, etc.)
13
+ - Any third-party libraries that use the modules above (i.e. `request`, `node-fetch`, `supertest`, etc.)
15
14
 
16
15
  ## Motivation
17
16
 
@@ -21,24 +20,74 @@ This library is a strip-to-bone implementation that provides as little abstracti
21
20
 
22
21
  ### How is this library different?
23
22
 
24
- As interception is often combined with request route matching, some libraries can determine whether a request should be mocked _before_ it actually happens. This approach is not suitable for this library, as it rather _intercepts all requests_ and then let's you decide which ones should be mocked. This affects the level at which interception happens, and also the way mocked/original responses are constructed, in comparison to other solutions.
23
+ A traditional API mocking implementation in Node.js looks roughly like this:
24
+
25
+ ```js
26
+ import http from 'http'
27
+
28
+ function applyMock() {
29
+ // Store the original request module.
30
+ const originalHttpRequest = http.request
31
+
32
+ // Rewrite the request module entirely.
33
+ http.request = function (...args) {
34
+ // Decide whether to handle this request before
35
+ // the actual request happens.
36
+ if (shouldMock(args)) {
37
+ // If so, never create a request, respond to it
38
+ // using the mocked response from this blackbox.
39
+ return coerceToResponse.bind(this, mock)
40
+ }
41
+
42
+ // Otherwise, construct the original request
43
+ // and perform it as-is (receives the original response).
44
+ return originalHttpRequest(...args)
45
+ }
46
+ }
47
+ ```
48
+
49
+ This library deviates from such implementation and uses _class extensions_ instead of module rewrites. Such deviation is necessary because, unlike other solutions that include request matching and can determine whether to mock requests _before_ they actually happen, this library is not opinionated about the mocked/bypassed nature of the requests. Instead, it _intercepts all requests_ and delegates the decision of mocking to the end consumer.
50
+
51
+ ```js
52
+ class NodeClientRequest extends ClientRequest {
53
+ async end(...args) {
54
+ // Check if there's a mocked response for this request.
55
+ // You control this in the "resolver" function.
56
+ const mockedResponse = await resolver(isomorphicRequest)
57
+
58
+ // If there is a mocked response, use it to respond to this
59
+ // request, finalizing it afterward as if it received that
60
+ // response from the actual server it connected to.
61
+ if (mockedResponse) {
62
+ this.respondWith(mockedResponse)
63
+ this.finish()
64
+ return
65
+ }
66
+
67
+ // Otherwise, perform the original "ClientRequest.prototype.end" call.
68
+ return super.end(...args)
69
+ }
70
+ }
71
+ ```
72
+
73
+ By extending the native modules, this library actually constructs requests as soon as they are constructed by the consumer. This enables all the request input validation and transformations done natively by Node.js—something that traditional solutions simply cannot do (they replace `http.ClientRequest` entirely). The class extension allows to fully utilize Node.js internals instead of polyfilling them, which results in more resilient mocks.
25
74
 
26
75
  ## What this library does
27
76
 
28
- This library monkey-patches the following native modules:
77
+ This library extends (or patches, where applicable) the following native modules:
29
78
 
30
79
  - `http.get`/`http.request`
31
80
  - `https.get`/`https.request`
32
81
  - `XMLHttpRequest`
33
82
  - `fetch`
34
83
 
35
- Once patched, it provisions the interception of requests and normalizes them to something called _isomorphic request instances_. That normalization ensures the same request handling for the consumer of the library, while requests originating from different modules may differ internally.
84
+ Once extended, it intercepts and normalizes all requests to the _isomorphic request instances_. The isomorphic request is an abstract representation of the request coming from different sources (`ClientRequest`, `XMLHttpRequest`, `window.Request`, etc.) that allows us to handle such requests in the same, unified manner.
36
85
 
37
- In its mocking phase, this library accepts an _isomorphic response instance_ that describes a module-agnostic mocked response. This allows you to respond to requests issued by different modules using the same response instance.
86
+ You can respond to an isomorphic request using an _isomorphic response_. In a similar way, the isomorphic response is a representation of the response to use for different requests. Responding to requests differs substantially when using modules like `http` or `XMLHttpRequest`. This library takes the responsibility for coercing isomorphic responses into appropriate responses depending on the request module automatically.
38
87
 
39
88
  ## What this library doesn't do
40
89
 
41
- - Does **not** provide any request matching logic.
90
+ - Does **not** provide any request matching logic;
42
91
  - Does **not** decide how to handle requests.
43
92
 
44
93
  ## Getting started
@@ -108,15 +157,15 @@ createRemoteResolver({
108
157
 
109
158
  ### Interceptors
110
159
 
111
- This library utilizes a concept of _interceptors_–functions that patch necessary modules, handle mocked responses, and restore patched modules.
160
+ This library utilizes a concept of _interceptors_–functions that extend request modules, handle mocked responses, and restore themselves when done.
112
161
 
113
- **List of interceptors:**
162
+ **Available interceptors:**
114
163
 
115
164
  - `/interceptors/ClientRequest`
116
165
  - `/interceptors/XMLHttpRequest`
117
166
  - `/interceptors/fetch`
118
167
 
119
- To use a single, or multiple interceptors, import and provide them to the `RequestInterceptor` constructor.
168
+ To use a single, or multiple interceptors, import and provide them to the `createInterceptor` function.
120
169
 
121
170
  ```js
122
171
  import { createInterceptor } from '@mswjs/interceptors'
@@ -124,12 +173,12 @@ import { interceptXMLHttpRequest } from '@mswjs/interceptors/lib/interceptors/XM
124
173
 
125
174
  // This `interceptor` instance would handle only XMLHttpRequest,
126
175
  // ignoring requests issued via `http`/`https` modules.
127
- const interceptor = new createInterceptor({
176
+ const interceptor = createInterceptor({
128
177
  modules: [interceptXMLHttpRequest],
129
178
  })
130
179
  ```
131
180
 
132
- > Interceptors are crucial in leveraging environment-specific module overrides. Certain environments (i.e. React Native) do not have access to native Node.js modules (like `http`). Importing such modules raises an exception, and must be avoided.
181
+ > Interceptors are crucial in leveraging environment-specific module overrides. Certain environments (i.e. React Native) do not have access to native Node.js modules (like `http`). Importing such modules throws an exception and should be avoided.
133
182
 
134
183
  ### Methods
135
184
 
@@ -145,8 +194,8 @@ interceptor.apply()
145
194
 
146
195
  Adds an event listener to one of the following supported events:
147
196
 
148
- - `request`, whenever a new request happens.
149
- - `response`, whenever a request library responds to a request.
197
+ - `request`, signals when a new request happens;
198
+ - `response`, signals when a response was sent.
150
199
 
151
200
  ```js
152
201
  interceptor.on('request', (request) => {
@@ -156,7 +205,7 @@ interceptor.on('request', (request) => {
156
205
 
157
206
  #### `.restore(): void`
158
207
 
159
- Restores all patched modules and stops intercepting future requests.
208
+ Restores all extensions and stops the interception of future requests.
160
209
 
161
210
  ```js
162
211
  interceptor.restore()
@@ -8,11 +8,18 @@ export declare type Observer = StrictEventEmitter<InterceptorEventsMap>;
8
8
  * A side-effect function to restore all the patched modules.
9
9
  */
10
10
  export declare type InterceptorCleanupFn = () => void;
11
+ export declare type RequestCredentials = 'omit' | 'include' | 'same-origin';
11
12
  export interface IsomorphicRequest {
12
13
  id: string;
13
14
  url: URL;
14
15
  method: string;
15
16
  headers: Headers;
17
+ /**
18
+ * The value of the request client's "credentials" option
19
+ * or a compatible alternative (i.e. `withCredentials` for `XMLHttpRequest`).
20
+ * Always equals to "omit" in Node.js.
21
+ */
22
+ credentials: RequestCredentials;
16
23
  body?: string;
17
24
  }
18
25
  export interface IsomorphicResponse {
@@ -1 +1 @@
1
- {"version":3,"file":"createInterceptor.js","sourceRoot":"","sources":["../src/createInterceptor.ts"],"names":[],"mappings":";;;AAEA,6DAAyD;AAgEzD,SAAgB,iBAAiB,CAAC,OAA2B;IAC3D,IAAM,QAAQ,GAAG,IAAI,yCAAkB,EAAwB,CAAA;IAC/D,IAAI,UAAU,GAA2B,EAAE,CAAA;IAE3C,OAAO;QACL,KAAK;YACH,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,UAAC,WAAW;gBAC3C,OAAO,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;YAChD,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,EAAE,YAAC,KAAK,EAAE,QAAQ;YAChB,QAAQ,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;QACvC,CAAC;QACD,OAAO;YACL,QAAQ,CAAC,kBAAkB,EAAE,CAAA;YAE7B,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE;gBAC3B,MAAM,IAAI,KAAK,CACb,0FAAwF,CACzF,CAAA;aACF;YAED,UAAU,CAAC,OAAO,CAAC,UAAC,OAAO,IAAK,OAAA,OAAO,EAAE,EAAT,CAAS,CAAC,CAAA;QAC5C,CAAC;KACF,CAAA;AACH,CAAC;AAzBD,8CAyBC"}
1
+ {"version":3,"file":"createInterceptor.js","sourceRoot":"","sources":["../src/createInterceptor.ts"],"names":[],"mappings":";;;AAEA,6DAAyD;AAwEzD,SAAgB,iBAAiB,CAAC,OAA2B;IAC3D,IAAM,QAAQ,GAAG,IAAI,yCAAkB,EAAwB,CAAA;IAC/D,IAAI,UAAU,GAA2B,EAAE,CAAA;IAE3C,OAAO;QACL,KAAK;YACH,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,UAAC,WAAW;gBAC3C,OAAO,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;YAChD,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,EAAE,YAAC,KAAK,EAAE,QAAQ;YAChB,QAAQ,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;QACvC,CAAC;QACD,OAAO;YACL,QAAQ,CAAC,kBAAkB,EAAE,CAAA;YAE7B,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE;gBAC3B,MAAM,IAAI,KAAK,CACb,0FAAwF,CACzF,CAAA;aACF;YAED,UAAU,CAAC,OAAO,CAAC,UAAC,OAAO,IAAK,OAAA,OAAO,EAAE,EAAT,CAAS,CAAC,CAAA;QAC5C,CAAC;KACF,CAAA;AACH,CAAC;AAzBD,8CAyBC"}
@@ -0,0 +1,38 @@
1
+ /// <reference types="node" />
2
+ import { ClientRequest } from 'http';
3
+ import type { Observer, Resolver } from '../../createInterceptor';
4
+ import { NormalizedClientRequestArgs } from './utils/normalizeClientRequestArgs';
5
+ import { ClientRequestWriteArgs } from './utils/normalizeClientRequestWriteArgs';
6
+ export declare type Protocol = 'http' | 'https';
7
+ export interface NodeClientOptions {
8
+ observer: Observer;
9
+ resolver: Resolver;
10
+ }
11
+ export declare class NodeClientRequest extends ClientRequest {
12
+ /**
13
+ * The list of internal Node.js errors to suppress while
14
+ * using the "mock" response source.
15
+ */
16
+ static suppressErrorCodes: string[];
17
+ private url;
18
+ private options;
19
+ private response;
20
+ private resolver;
21
+ private observer;
22
+ private log;
23
+ private chunks;
24
+ private responseSource;
25
+ private capturedError?;
26
+ requestBody: Buffer[];
27
+ constructor([url, requestOptions, callback]: NormalizedClientRequestArgs, options: NodeClientOptions);
28
+ write(...args: ClientRequestWriteArgs): boolean;
29
+ end(...args: any): Promise<void>;
30
+ emit(event: string, ...data: any[]): boolean;
31
+ private respondWith;
32
+ /**
33
+ * Terminates a pending request.
34
+ */
35
+ private terminate;
36
+ private getRequestBody;
37
+ private toIsomorphicRequest;
38
+ }
@@ -0,0 +1,420 @@
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
18
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
19
+ return new (P || (P = Promise))(function (resolve, reject) {
20
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
21
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
22
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
23
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
24
+ });
25
+ };
26
+ var __generator = (this && this.__generator) || function (thisArg, body) {
27
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
28
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
29
+ function verb(n) { return function (v) { return step([n, v]); }; }
30
+ function step(op) {
31
+ if (f) throw new TypeError("Generator is already executing.");
32
+ while (_) try {
33
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
34
+ if (y = 0, t) op = [op[0] & 2, t.value];
35
+ switch (op[0]) {
36
+ case 0: case 1: t = op; break;
37
+ case 4: _.label++; return { value: op[1], done: false };
38
+ case 5: _.label++; y = op[1]; op = [0]; continue;
39
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
40
+ default:
41
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
42
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
43
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
44
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
45
+ if (t[2]) _.ops.pop();
46
+ _.trys.pop(); continue;
47
+ }
48
+ op = body.call(thisArg, _);
49
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
50
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
51
+ }
52
+ };
53
+ var __read = (this && this.__read) || function (o, n) {
54
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
55
+ if (!m) return o;
56
+ var i = m.call(o), r, ar = [], e;
57
+ try {
58
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
59
+ }
60
+ catch (error) { e = { error: error }; }
61
+ finally {
62
+ try {
63
+ if (r && !r.done && (m = i["return"])) m.call(i);
64
+ }
65
+ finally { if (e) throw e.error; }
66
+ }
67
+ return ar;
68
+ };
69
+ var __spreadArray = (this && this.__spreadArray) || function (to, from) {
70
+ for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
71
+ to[j] = from[i];
72
+ return to;
73
+ };
74
+ var __values = (this && this.__values) || function(o) {
75
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
76
+ if (m) return m.call(o);
77
+ if (o && typeof o.length === "number") return {
78
+ next: function () {
79
+ if (o && i >= o.length) o = void 0;
80
+ return { value: o && o[i++], done: !o };
81
+ }
82
+ };
83
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
84
+ };
85
+ Object.defineProperty(exports, "__esModule", { value: true });
86
+ exports.NodeClientRequest = void 0;
87
+ var debug_1 = require("debug");
88
+ var http_1 = require("http");
89
+ var until_1 = require("@open-draft/until");
90
+ var lib_1 = require("headers-utils/lib");
91
+ var uuid_1 = require("../../utils/uuid");
92
+ var concatChunkToBuffer_1 = require("./utils/concatChunkToBuffer");
93
+ var normalizeClientRequestEndArgs_1 = require("./utils/normalizeClientRequestEndArgs");
94
+ var toIsoResponse_1 = require("../../utils/toIsoResponse");
95
+ var getIncomingMessageBody_1 = require("./utils/getIncomingMessageBody");
96
+ var bodyBufferToString_1 = require("./utils/bodyBufferToString");
97
+ var normalizeClientRequestWriteArgs_1 = require("./utils/normalizeClientRequestWriteArgs");
98
+ var cloneIncomingMessage_1 = require("./utils/cloneIncomingMessage");
99
+ var NodeClientRequest = /** @class */ (function (_super) {
100
+ __extends(NodeClientRequest, _super);
101
+ function NodeClientRequest(_a, options) {
102
+ var _b = __read(_a, 3), url = _b[0], requestOptions = _b[1], callback = _b[2];
103
+ var _this = _super.call(this, requestOptions, callback) || this;
104
+ _this.chunks = [];
105
+ _this.responseSource = 'mock';
106
+ _this.requestBody = [];
107
+ _this.log = debug_1.debug("http " + requestOptions.method + " " + url.href);
108
+ _this.log('constructing ClientRequest...', {
109
+ url: url,
110
+ requestOptions: requestOptions,
111
+ callback: callback,
112
+ });
113
+ _this.url = url;
114
+ _this.options = requestOptions;
115
+ _this.resolver = options.resolver;
116
+ _this.observer = options.observer;
117
+ // Construct a mocked response message.
118
+ _this.response = new http_1.IncomingMessage(_this.socket);
119
+ return _this;
120
+ }
121
+ NodeClientRequest.prototype.write = function () {
122
+ var _this = this;
123
+ var args = [];
124
+ for (var _i = 0; _i < arguments.length; _i++) {
125
+ args[_i] = arguments[_i];
126
+ }
127
+ var _a = __read(normalizeClientRequestWriteArgs_1.normalizeClientRequestWriteArgs(args), 3), chunk = _a[0], encoding = _a[1], callback = _a[2];
128
+ this.log('write:', { chunk: chunk, encoding: encoding, callback: callback });
129
+ this.chunks.push({
130
+ chunk: chunk,
131
+ encoding: encoding,
132
+ callback: function (error) {
133
+ if (error) {
134
+ _this.log('error while writing chunk!', error);
135
+ }
136
+ else {
137
+ _this.log('request chunk successfully written!');
138
+ }
139
+ callback === null || callback === void 0 ? void 0 : callback(error);
140
+ },
141
+ });
142
+ this.log('chunk successfully stored!');
143
+ this.requestBody = concatChunkToBuffer_1.concatChunkToBuffer(chunk, this.requestBody);
144
+ // Do not write the request body chunks to prevent
145
+ // the Socket from sending data to a potentially existing
146
+ // server when there is a mocked response defined.
147
+ return true;
148
+ };
149
+ NodeClientRequest.prototype.end = function () {
150
+ var args = [];
151
+ for (var _i = 0; _i < arguments.length; _i++) {
152
+ args[_i] = arguments[_i];
153
+ }
154
+ return __awaiter(this, void 0, void 0, function () {
155
+ var _a, chunk, encoding, callback, requestBody, isomorphicRequest, _b, resolverError, mockedResponse, isomorphicResponse, _c, _d, _e, chunk_1, encoding_1, callback_1;
156
+ var e_1, _f;
157
+ var _this = this;
158
+ return __generator(this, function (_g) {
159
+ switch (_g.label) {
160
+ case 0:
161
+ this.log('end', args);
162
+ _a = __read(normalizeClientRequestEndArgs_1.normalizeClientRequestEndArgs.apply(void 0, __spreadArray([], __read(args))), 3), chunk = _a[0], encoding = _a[1], callback = _a[2];
163
+ this.log('normalized arguments:', { chunk: chunk, encoding: encoding, callback: callback });
164
+ requestBody = this.getRequestBody(chunk);
165
+ isomorphicRequest = this.toIsomorphicRequest(requestBody);
166
+ this.observer.emit('request', isomorphicRequest);
167
+ this.log('executing response resolver...');
168
+ return [4 /*yield*/, until_1.until(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
169
+ return [2 /*return*/, this.resolver(isomorphicRequest, this.response)];
170
+ }); }); })
171
+ // Halt the request whenever the resolver throws an exception.
172
+ ];
173
+ case 1:
174
+ _b = __read.apply(void 0, [_g.sent()
175
+ // Halt the request whenever the resolver throws an exception.
176
+ , 2]), resolverError = _b[0], mockedResponse = _b[1];
177
+ // Halt the request whenever the resolver throws an exception.
178
+ if (resolverError) {
179
+ this.log('encountered resolver exception, aborting request...', resolverError);
180
+ this.emit('error', resolverError);
181
+ this.terminate();
182
+ return [2 /*return*/];
183
+ }
184
+ if (mockedResponse) {
185
+ this.log('received mocked response:', mockedResponse);
186
+ this.responseSource = 'mock';
187
+ isomorphicResponse = toIsoResponse_1.toIsoResponse(mockedResponse);
188
+ this.respondWith(mockedResponse);
189
+ this.log(isomorphicResponse.status, isomorphicResponse.statusText, isomorphicResponse.body, '(MOCKED)');
190
+ callback === null || callback === void 0 ? void 0 : callback();
191
+ this.observer.emit('response', isomorphicRequest, isomorphicResponse);
192
+ return [2 /*return*/];
193
+ }
194
+ this.log('no mocked response found!');
195
+ // Set the response source to "bypass".
196
+ // Any errors emitted past this point are not suppressed.
197
+ this.responseSource = 'bypass';
198
+ // Propagate previously captured errors.
199
+ // For example, a ECONNREFUSED error when connecting to a non-existing host.
200
+ if (this.capturedError) {
201
+ this.emit('error', this.capturedError);
202
+ return [2 /*return*/];
203
+ }
204
+ // Write the request body chunks in the order of ".write()" calls.
205
+ // Note that no request body has been written prior to this point
206
+ // in order to prevent the Socket to communicate with a potentially
207
+ // existing server.
208
+ this.log('writing request chunks...', this.chunks);
209
+ try {
210
+ for (_c = __values(this.chunks), _d = _c.next(); !_d.done; _d = _c.next()) {
211
+ _e = _d.value, chunk_1 = _e.chunk, encoding_1 = _e.encoding, callback_1 = _e.callback;
212
+ encoding_1
213
+ ? _super.prototype.write.call(this, chunk_1, encoding_1, callback_1)
214
+ : _super.prototype.write.call(this, chunk_1, callback_1);
215
+ }
216
+ }
217
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
218
+ finally {
219
+ try {
220
+ if (_d && !_d.done && (_f = _c.return)) _f.call(_c);
221
+ }
222
+ finally { if (e_1) throw e_1.error; }
223
+ }
224
+ this.once('error', function (error) {
225
+ _this.log('original request error:', error);
226
+ });
227
+ this.once('abort', function () {
228
+ _this.log('original request aborted!');
229
+ });
230
+ this.once('response-internal', function (response) { return __awaiter(_this, void 0, void 0, function () {
231
+ var responseBody;
232
+ return __generator(this, function (_a) {
233
+ switch (_a.label) {
234
+ case 0: return [4 /*yield*/, getIncomingMessageBody_1.getIncomingMessageBody(response)];
235
+ case 1:
236
+ responseBody = _a.sent();
237
+ this.log(response.statusCode, response.statusMessage, responseBody);
238
+ this.log('original response headers:', response.headers);
239
+ this.observer.emit('response', isomorphicRequest, {
240
+ status: response.statusCode || 200,
241
+ statusText: response.statusMessage || 'OK',
242
+ headers: lib_1.objectToHeaders(response.headers),
243
+ body: responseBody,
244
+ });
245
+ return [2 /*return*/];
246
+ }
247
+ });
248
+ }); });
249
+ this.log('performing original request...');
250
+ return [2 /*return*/, _super.prototype.end.apply(this, __spreadArray([], __read([
251
+ chunk,
252
+ encoding,
253
+ function () {
254
+ _this.log('original request end!');
255
+ callback === null || callback === void 0 ? void 0 : callback();
256
+ },
257
+ ].filter(Boolean))))];
258
+ }
259
+ });
260
+ });
261
+ };
262
+ NodeClientRequest.prototype.emit = function (event) {
263
+ var data = [];
264
+ for (var _i = 1; _i < arguments.length; _i++) {
265
+ data[_i - 1] = arguments[_i];
266
+ }
267
+ this.log('event:%s', event);
268
+ if (event === 'response') {
269
+ this.log('found "response" event, cloning the response...');
270
+ try {
271
+ /**
272
+ * Clone the response object when emitting the "response" event.
273
+ * This prevents the response body stream from locking
274
+ * and allows reading it twice:
275
+ * 1. Internal "response" event from the observer.
276
+ * 2. Any external response body listeners.
277
+ * @see https://github.com/mswjs/interceptors/issues/161
278
+ */
279
+ var response = data[0];
280
+ var firstClone = cloneIncomingMessage_1.cloneIncomingMessage(response);
281
+ var secondClone = cloneIncomingMessage_1.cloneIncomingMessage(response);
282
+ this.emit('response-internal', secondClone);
283
+ this.log('response successfuly cloned, emitting "response" event...');
284
+ return _super.prototype.emit.apply(this, __spreadArray([event, firstClone], __read(data.slice(1))));
285
+ }
286
+ catch (error) {
287
+ this.log('error when cloning response:', error);
288
+ return _super.prototype.emit.apply(this, __spreadArray([event], __read(data)));
289
+ }
290
+ }
291
+ if (event === 'error') {
292
+ var error = data[0];
293
+ var errorCode = error.code || '';
294
+ this.log('error:\n', error);
295
+ // Supress certain errors while using the "mock" source.
296
+ // For example, no need to destroy this request if it connects
297
+ // to a non-existing hostname but has a mocked response.
298
+ if (this.responseSource === 'mock' &&
299
+ NodeClientRequest.suppressErrorCodes.includes(errorCode)) {
300
+ // Capture the first emitted error in order to replay
301
+ // it later if this request won't have any mocked response.
302
+ if (!this.capturedError) {
303
+ this.capturedError = error;
304
+ }
305
+ return false;
306
+ }
307
+ }
308
+ return _super.prototype.emit.apply(this, __spreadArray([event], __read(data)));
309
+ };
310
+ NodeClientRequest.prototype.respondWith = function (mockedResponse) {
311
+ var e_2, _a, _b;
312
+ this.log('responding with a mocked response...', mockedResponse);
313
+ var status = mockedResponse.status, statusText = mockedResponse.statusText, headers = mockedResponse.headers, body = mockedResponse.body;
314
+ this.response.statusCode = status;
315
+ this.response.statusMessage = statusText;
316
+ if (headers) {
317
+ this.response.headers = {};
318
+ try {
319
+ for (var _c = __values(Object.entries(headers)), _d = _c.next(); !_d.done; _d = _c.next()) {
320
+ var _e = __read(_d.value, 2), headerName = _e[0], headerValue = _e[1];
321
+ (_b = this.response.rawHeaders).push.apply(_b, __spreadArray([headerName], __read((Array.isArray(headerValue) ? headerValue : [headerValue]))));
322
+ var insensitiveHeaderName = headerName.toLowerCase();
323
+ var prevHeaders = this.response.headers[insensitiveHeaderName];
324
+ this.response.headers[insensitiveHeaderName] = prevHeaders
325
+ ? Array.prototype.concat([], prevHeaders, headerValue)
326
+ : headerValue;
327
+ }
328
+ }
329
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
330
+ finally {
331
+ try {
332
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
333
+ }
334
+ finally { if (e_2) throw e_2.error; }
335
+ }
336
+ }
337
+ this.log('mocked response headers ready:', headers);
338
+ if (body) {
339
+ this.response.push(Buffer.from(body));
340
+ }
341
+ // Push "null" to indicate that the response body is complete
342
+ // and shouldn't be written to anymore.
343
+ this.response.push(null);
344
+ this.response.complete = true;
345
+ /**
346
+ * Set the internal "res" property to the mocked "OutgoingMessage"
347
+ * to make the "ClientRequest" instance think there's data received
348
+ * from the socket.
349
+ * @see https://github.com/nodejs/node/blob/9c405f2591f5833d0247ed0fafdcd68c5b14ce7a/lib/_http_client.js#L501
350
+ */
351
+ // @ts-ignore
352
+ this.res = this.response;
353
+ this.finished = true;
354
+ Object.defineProperty(this, 'writableEnded', {
355
+ value: true,
356
+ });
357
+ this.emit('finish');
358
+ this.emit('response', this.response);
359
+ this.terminate();
360
+ };
361
+ /**
362
+ * Terminates a pending request.
363
+ */
364
+ NodeClientRequest.prototype.terminate = function () {
365
+ // @ts-ignore
366
+ this.agent.destroy();
367
+ };
368
+ NodeClientRequest.prototype.getRequestBody = function (chunk) {
369
+ var writtenRequestBody = bodyBufferToString_1.bodyBufferToString(Buffer.concat(this.requestBody));
370
+ this.log('written request body:', writtenRequestBody);
371
+ // Write the last request body chunk to the internal request body buffer.
372
+ if (chunk) {
373
+ this.requestBody = concatChunkToBuffer_1.concatChunkToBuffer(chunk, this.requestBody);
374
+ }
375
+ var resolvedRequestBody = bodyBufferToString_1.bodyBufferToString(Buffer.concat(this.requestBody));
376
+ this.log('resolved request body:', resolvedRequestBody);
377
+ return resolvedRequestBody;
378
+ };
379
+ NodeClientRequest.prototype.toIsomorphicRequest = function (body) {
380
+ var e_3, _a;
381
+ this.log('creating isomorphic request object...');
382
+ var outgoingHeaders = this.getHeaders();
383
+ this.log('request outgoing headers:', outgoingHeaders);
384
+ var headers = new lib_1.Headers();
385
+ try {
386
+ for (var _b = __values(Object.entries(outgoingHeaders)), _c = _b.next(); !_c.done; _c = _b.next()) {
387
+ var _d = __read(_c.value, 2), headerName = _d[0], headerValue = _d[1];
388
+ if (!headerValue) {
389
+ continue;
390
+ }
391
+ headers.set(headerName.toLowerCase(), headerValue.toString());
392
+ }
393
+ }
394
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
395
+ finally {
396
+ try {
397
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
398
+ }
399
+ finally { if (e_3) throw e_3.error; }
400
+ }
401
+ var isomorphicRequest = {
402
+ id: uuid_1.uuidv4(),
403
+ url: this.url,
404
+ method: this.options.method || 'GET',
405
+ credentials: 'omit',
406
+ headers: headers,
407
+ body: body,
408
+ };
409
+ this.log('successfully created isomorphic request!', isomorphicRequest);
410
+ return isomorphicRequest;
411
+ };
412
+ /**
413
+ * The list of internal Node.js errors to suppress while
414
+ * using the "mock" response source.
415
+ */
416
+ NodeClientRequest.suppressErrorCodes = ['ENOTFOUND', 'ECONNREFUSED', 'ECONNRESET'];
417
+ return NodeClientRequest;
418
+ }(http_1.ClientRequest));
419
+ exports.NodeClientRequest = NodeClientRequest;
420
+ //# sourceMappingURL=NodeClientRequest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NodeClientRequest.js","sourceRoot":"","sources":["../../../src/interceptors/ClientRequest/NodeClientRequest.ts"],"names":[],"mappings":"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"}