@zimic/interceptor 1.1.2 → 1.1.3-canary.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-AMKVGJZN.mjs → chunk-5JHZWURB.mjs} +16 -104
- package/dist/chunk-5JHZWURB.mjs.map +1 -0
- package/dist/{chunk-RQ2YYT5B.js → chunk-NWA64QXK.js} +15 -103
- package/dist/chunk-NWA64QXK.js.map +1 -0
- package/dist/cli.js +18 -18
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/cli.mjs.map +1 -1
- package/dist/http.d.ts +30 -19
- package/dist/http.js +25 -105
- package/dist/http.js.map +1 -1
- package/dist/http.mjs +24 -104
- package/dist/http.mjs.map +1 -1
- package/dist/server.js +6 -6
- package/dist/server.mjs +1 -1
- package/package.json +4 -4
- package/src/http/index.ts +33 -2
- package/src/http/interceptor/HttpInterceptorClient.ts +2 -2
- package/src/http/interceptorWorker/HttpInterceptorWorker.ts +11 -106
- package/src/http/interceptorWorker/LocalHttpInterceptorWorker.ts +2 -2
- package/src/server/InterceptorServer.ts +2 -2
- package/dist/chunk-AMKVGJZN.mjs.map +0 -1
- package/dist/chunk-RQ2YYT5B.js.map +0 -1
- package/src/http/interceptorWorker/errors/InvalidFormDataError.ts +0 -13
- package/src/http/interceptorWorker/errors/InvalidJSONError.ts +0 -13
package/dist/server.js
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkNWA64QXK_js = require('./chunk-NWA64QXK.js');
|
|
4
4
|
require('./chunk-DGUM43GV.js');
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
Object.defineProperty(exports, "DEFAULT_ACCESS_CONTROL_HEADERS", {
|
|
9
9
|
enumerable: true,
|
|
10
|
-
get: function () { return
|
|
10
|
+
get: function () { return chunkNWA64QXK_js.DEFAULT_ACCESS_CONTROL_HEADERS; }
|
|
11
11
|
});
|
|
12
12
|
Object.defineProperty(exports, "DEFAULT_PREFLIGHT_STATUS_CODE", {
|
|
13
13
|
enumerable: true,
|
|
14
|
-
get: function () { return
|
|
14
|
+
get: function () { return chunkNWA64QXK_js.DEFAULT_PREFLIGHT_STATUS_CODE; }
|
|
15
15
|
});
|
|
16
16
|
Object.defineProperty(exports, "NotRunningInterceptorServerError", {
|
|
17
17
|
enumerable: true,
|
|
18
|
-
get: function () { return
|
|
18
|
+
get: function () { return chunkNWA64QXK_js.NotRunningInterceptorServerError_default; }
|
|
19
19
|
});
|
|
20
20
|
Object.defineProperty(exports, "RunningInterceptorServerError", {
|
|
21
21
|
enumerable: true,
|
|
22
|
-
get: function () { return
|
|
22
|
+
get: function () { return chunkNWA64QXK_js.RunningInterceptorServerError_default; }
|
|
23
23
|
});
|
|
24
24
|
Object.defineProperty(exports, "createInterceptorServer", {
|
|
25
25
|
enumerable: true,
|
|
26
|
-
get: function () { return
|
|
26
|
+
get: function () { return chunkNWA64QXK_js.createInterceptorServer; }
|
|
27
27
|
});
|
|
28
28
|
//# sourceMappingURL=server.js.map
|
|
29
29
|
//# sourceMappingURL=server.js.map
|
package/dist/server.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { DEFAULT_ACCESS_CONTROL_HEADERS, DEFAULT_PREFLIGHT_STATUS_CODE, NotRunningInterceptorServerError_default as NotRunningInterceptorServerError, RunningInterceptorServerError_default as RunningInterceptorServerError, createInterceptorServer } from './chunk-
|
|
1
|
+
export { DEFAULT_ACCESS_CONTROL_HEADERS, DEFAULT_PREFLIGHT_STATUS_CODE, NotRunningInterceptorServerError_default as NotRunningInterceptorServerError, RunningInterceptorServerError_default as RunningInterceptorServerError, createInterceptorServer } from './chunk-5JHZWURB.mjs';
|
|
2
2
|
import './chunk-BJTO5JO5.mjs';
|
|
3
3
|
//# sourceMappingURL=server.mjs.map
|
|
4
4
|
//# sourceMappingURL=server.mjs.map
|
package/package.json
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"api",
|
|
15
15
|
"static"
|
|
16
16
|
],
|
|
17
|
-
"version": "1.1.
|
|
17
|
+
"version": "1.1.3-canary.1",
|
|
18
18
|
"homepage": "https://zimic.dev/docs/interceptor",
|
|
19
19
|
"repository": {
|
|
20
20
|
"type": "git",
|
|
@@ -105,13 +105,13 @@
|
|
|
105
105
|
"typescript": "^5.9.2",
|
|
106
106
|
"vitest": "^3.2.4",
|
|
107
107
|
"@zimic/eslint-config-node": "0.0.0",
|
|
108
|
-
"@zimic/lint-staged-config": "0.0.0",
|
|
109
108
|
"@zimic/tsconfig": "0.0.0",
|
|
110
|
-
"@zimic/utils": "0.0.0"
|
|
109
|
+
"@zimic/utils": "0.0.0",
|
|
110
|
+
"@zimic/lint-staged-config": "0.0.0"
|
|
111
111
|
},
|
|
112
112
|
"peerDependencies": {
|
|
113
113
|
"typescript": ">=5.0.0",
|
|
114
|
-
"@zimic/http": "^1.1.0 || 1.
|
|
114
|
+
"@zimic/http": "^1.1.0 || 1.2.0-canary.0"
|
|
115
115
|
},
|
|
116
116
|
"peerDependenciesMeta": {
|
|
117
117
|
"typescript": {
|
package/src/http/index.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
InvalidFormDataError as HttpInvalidFormDataError,
|
|
3
|
+
InvalidJSONError as HttpInvalidJSONError,
|
|
4
|
+
} from '@zimic/http';
|
|
5
|
+
|
|
1
6
|
export { default as RunningHttpInterceptorError } from './interceptor/errors/RunningHttpInterceptorError';
|
|
2
7
|
export { default as NotRunningHttpInterceptorError } from './interceptor/errors/NotRunningHttpInterceptorError';
|
|
3
8
|
export { default as UnknownHttpInterceptorPlatformError } from './interceptor/errors/UnknownHttpInterceptorPlatformError';
|
|
4
9
|
export { default as UnknownHttpInterceptorTypeError } from './interceptor/errors/UnknownHttpInterceptorTypeError';
|
|
5
10
|
export { default as RequestSavingSafeLimitExceededError } from './interceptor/errors/RequestSavingSafeLimitExceededError';
|
|
6
11
|
|
|
7
|
-
export { default as InvalidFormDataError } from './interceptorWorker/errors/InvalidFormDataError';
|
|
8
|
-
export { default as InvalidJSONError } from './interceptorWorker/errors/InvalidJSONError';
|
|
9
12
|
export { default as UnregisteredBrowserServiceWorkerError } from './interceptorWorker/errors/UnregisteredBrowserServiceWorkerError';
|
|
10
13
|
|
|
11
14
|
export { default as DisabledRequestSavingError } from './requestHandler/errors/DisabledRequestSavingError';
|
|
@@ -51,3 +54,31 @@ export type { InferHttpInterceptorSchema } from './interceptor/types/schema';
|
|
|
51
54
|
export type { LocalHttpInterceptor, RemoteHttpInterceptor, HttpInterceptor } from './interceptor/types/public';
|
|
52
55
|
|
|
53
56
|
export { createHttpInterceptor } from './interceptor/factory';
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Error thrown when a value is not valid {@link https://developer.mozilla.org/docs/Web/API/FormData FormData}. HTTP
|
|
60
|
+
* interceptors might throw this error when trying to parse the body of a request or response with the header
|
|
61
|
+
* `'content-type': 'multipart/form-data'`, if the content cannot be parsed to form data.
|
|
62
|
+
*
|
|
63
|
+
* @deprecated This type has been moved to {@link https://zimic.dev/docs/http `@zimic/http`}. Please import
|
|
64
|
+
* `InvalidFormDataError` from `@zimic/http` instead.
|
|
65
|
+
*
|
|
66
|
+
* ```ts
|
|
67
|
+
* import { InvalidFormDataError } from '@zimic/http';
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export class InvalidFormDataError extends HttpInvalidFormDataError {}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Error thrown when a value is not valid JSON. HTTP interceptors might throw this error when trying to parse the body
|
|
74
|
+
* of a request or response with the header `'content-type': 'application/json'`, if the content cannot be parsed to
|
|
75
|
+
* JSON.
|
|
76
|
+
*
|
|
77
|
+
* @deprecated This type has been moved to {@link https://zimic.dev/docs/http `@zimic/http`}. Please import
|
|
78
|
+
* `InvalidJSONError` from `@zimic/http` instead.
|
|
79
|
+
*
|
|
80
|
+
* ```ts
|
|
81
|
+
* import { InvalidJSONError } from '@zimic/http';
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export class InvalidJSONError extends HttpInvalidJSONError {}
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from '@zimic/http';
|
|
10
10
|
import { Default, PossiblePromise } from '@zimic/utils/types';
|
|
11
11
|
import createRegexFromPath from '@zimic/utils/url/createRegexFromPath';
|
|
12
|
-
import
|
|
12
|
+
import excludeNonPathParams from '@zimic/utils/url/excludeNonPathParams';
|
|
13
13
|
import validateURLProtocol from '@zimic/utils/url/validateURLProtocol';
|
|
14
14
|
|
|
15
15
|
import { isServerSide } from '@/utils/environment';
|
|
@@ -109,7 +109,7 @@ class HttpInterceptorClient<
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
validateURLProtocol(newBaseURL, SUPPORTED_BASE_URL_PROTOCOLS);
|
|
112
|
-
|
|
112
|
+
excludeNonPathParams(newBaseURL);
|
|
113
113
|
|
|
114
114
|
this._baseURL = newBaseURL;
|
|
115
115
|
}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
HttpSchema,
|
|
9
9
|
HttpStatusCode,
|
|
10
10
|
InferPathParams,
|
|
11
|
-
|
|
11
|
+
parseHttpBody,
|
|
12
12
|
HttpSearchParams,
|
|
13
13
|
} from '@zimic/http';
|
|
14
14
|
import isDefined from '@zimic/utils/data/isDefined';
|
|
@@ -33,8 +33,6 @@ import {
|
|
|
33
33
|
HttpInterceptorResponse,
|
|
34
34
|
} from '../requestHandler/types/requests';
|
|
35
35
|
import { DEFAULT_UNHANDLED_REQUEST_STRATEGY } from './constants';
|
|
36
|
-
import InvalidFormDataError from './errors/InvalidFormDataError';
|
|
37
|
-
import InvalidJSONError from './errors/InvalidJSONError';
|
|
38
36
|
import { MSWHttpResponseFactory } from './types/msw';
|
|
39
37
|
import { HttpInterceptorWorkerType } from './types/options';
|
|
40
38
|
|
|
@@ -208,6 +206,7 @@ abstract class HttpInterceptorWorker {
|
|
|
208
206
|
|
|
209
207
|
if (
|
|
210
208
|
typeof declaration.body === 'string' ||
|
|
209
|
+
declaration.body === null ||
|
|
211
210
|
declaration.body === undefined ||
|
|
212
211
|
declaration.body instanceof FormData ||
|
|
213
212
|
declaration.body instanceof URLSearchParams ||
|
|
@@ -235,7 +234,11 @@ abstract class HttpInterceptorWorker {
|
|
|
235
234
|
const rawRequestClone = rawRequest.clone();
|
|
236
235
|
|
|
237
236
|
type BodySchema = Default<Default<MethodSchema['request']>['body']>;
|
|
238
|
-
|
|
237
|
+
|
|
238
|
+
const parsedBody = await parseHttpBody<BodySchema>(rawRequest).catch((error: unknown) => {
|
|
239
|
+
logger.error('Failed to parse request body:', error);
|
|
240
|
+
return null;
|
|
241
|
+
});
|
|
239
242
|
|
|
240
243
|
type HeadersSchema = Default<Default<MethodSchema['request']>['headers']>;
|
|
241
244
|
const headers = new HttpHeaders<HeadersSchema>(rawRequest.headers);
|
|
@@ -311,7 +314,10 @@ abstract class HttpInterceptorWorker {
|
|
|
311
314
|
const rawResponseClone = rawResponse.clone();
|
|
312
315
|
|
|
313
316
|
type BodySchema = Default<Default<Default<MethodSchema['response']>[StatusCode]>['body']>;
|
|
314
|
-
const parsedBody = await
|
|
317
|
+
const parsedBody = await parseHttpBody<BodySchema>(rawResponse).catch((error: unknown) => {
|
|
318
|
+
logger.error('Failed to parse response body:', error);
|
|
319
|
+
return null;
|
|
320
|
+
});
|
|
315
321
|
|
|
316
322
|
type HeadersSchema = Default<Default<Default<MethodSchema['response']>[StatusCode]>['headers']>;
|
|
317
323
|
const headers = new HttpHeaders<HeadersSchema>(rawResponse.headers);
|
|
@@ -376,107 +382,6 @@ abstract class HttpInterceptorWorker {
|
|
|
376
382
|
return params as InferPathParams<Path>;
|
|
377
383
|
}
|
|
378
384
|
|
|
379
|
-
static async parseRawBody<Body extends HttpBody>(resource: Request | Response) {
|
|
380
|
-
const contentType = resource.headers.get('content-type');
|
|
381
|
-
|
|
382
|
-
try {
|
|
383
|
-
if (contentType) {
|
|
384
|
-
if (contentType.startsWith('application/json')) {
|
|
385
|
-
return await this.parseRawBodyAsJSON<Body>(resource);
|
|
386
|
-
}
|
|
387
|
-
if (contentType.startsWith('multipart/form-data')) {
|
|
388
|
-
return await this.parseRawBodyAsFormData<Body>(resource);
|
|
389
|
-
}
|
|
390
|
-
if (contentType.startsWith('application/x-www-form-urlencoded')) {
|
|
391
|
-
return await this.parseRawBodyAsSearchParams<Body>(resource);
|
|
392
|
-
}
|
|
393
|
-
if (contentType.startsWith('text/') || contentType.startsWith('application/xml')) {
|
|
394
|
-
return await this.parseRawBodyAsText<Body>(resource);
|
|
395
|
-
}
|
|
396
|
-
if (
|
|
397
|
-
contentType.startsWith('application/') ||
|
|
398
|
-
contentType.startsWith('image/') ||
|
|
399
|
-
contentType.startsWith('audio/') ||
|
|
400
|
-
contentType.startsWith('font/') ||
|
|
401
|
-
contentType.startsWith('video/') ||
|
|
402
|
-
contentType.startsWith('multipart/')
|
|
403
|
-
) {
|
|
404
|
-
return await this.parseRawBodyAsBlob<Body>(resource);
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
const resourceClone = resource.clone();
|
|
409
|
-
|
|
410
|
-
try {
|
|
411
|
-
return await this.parseRawBodyAsJSON<Body>(resource);
|
|
412
|
-
} catch {
|
|
413
|
-
return await this.parseRawBodyAsBlob<Body>(resourceClone);
|
|
414
|
-
}
|
|
415
|
-
} catch (error) {
|
|
416
|
-
console.error(error);
|
|
417
|
-
return null;
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
private static async parseRawBodyAsJSON<Body extends HttpBody>(resource: Request | Response) {
|
|
422
|
-
const bodyAsText = await resource.text();
|
|
423
|
-
|
|
424
|
-
if (!bodyAsText.trim()) {
|
|
425
|
-
return null;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
try {
|
|
429
|
-
const bodyAsJSON = JSON.parse(bodyAsText) as Body;
|
|
430
|
-
return bodyAsJSON;
|
|
431
|
-
} catch {
|
|
432
|
-
throw new InvalidJSONError(bodyAsText);
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
private static async parseRawBodyAsSearchParams<Body extends HttpBody>(resource: Request | Response) {
|
|
437
|
-
const bodyAsText = await resource.text();
|
|
438
|
-
|
|
439
|
-
if (!bodyAsText.trim()) {
|
|
440
|
-
return null;
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
const bodyAsSearchParams = new HttpSearchParams(bodyAsText);
|
|
444
|
-
return bodyAsSearchParams as Body;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
private static async parseRawBodyAsFormData<Body extends HttpBody>(resource: Request | Response) {
|
|
448
|
-
const resourceClone = resource.clone();
|
|
449
|
-
|
|
450
|
-
try {
|
|
451
|
-
const bodyAsRawFormData = await resource.formData();
|
|
452
|
-
|
|
453
|
-
const bodyAsFormData = new HttpFormData();
|
|
454
|
-
for (const [key, value] of bodyAsRawFormData) {
|
|
455
|
-
bodyAsFormData.append(key, value as string);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
return bodyAsFormData as Body;
|
|
459
|
-
} catch {
|
|
460
|
-
const bodyAsText = await resourceClone.text();
|
|
461
|
-
|
|
462
|
-
if (!bodyAsText.trim()) {
|
|
463
|
-
return null;
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
throw new InvalidFormDataError(bodyAsText);
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
private static async parseRawBodyAsBlob<Body extends HttpBody>(resource: Request | Response) {
|
|
471
|
-
const bodyAsBlob = await resource.blob();
|
|
472
|
-
return bodyAsBlob as Body;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
private static async parseRawBodyAsText<Body extends HttpBody>(resource: Request | Response) {
|
|
476
|
-
const bodyAsText = await resource.text();
|
|
477
|
-
return (bodyAsText || null) as Body;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
385
|
static async logUnhandledRequestWarning(rawRequest: Request, action: UnhandledRequestStrategy.Action) {
|
|
481
386
|
const request = await this.parseRawRequest(rawRequest);
|
|
482
387
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HttpRequest, HttpResponse, HttpMethod, HttpSchema } from '@zimic/http';
|
|
2
2
|
import createRegexFromPath from '@zimic/utils/url/createRegexFromPath';
|
|
3
|
-
import
|
|
3
|
+
import excludeNonPathParams from '@zimic/utils/url/excludeNonPathParams';
|
|
4
4
|
import validatePathParams from '@zimic/utils/url/validatePathParams';
|
|
5
5
|
import { SharedOptions as MSWWorkerSharedOptions, http, passthrough } from 'msw';
|
|
6
6
|
import * as mswBrowser from 'msw/browser';
|
|
@@ -210,7 +210,7 @@ class LocalHttpInterceptorWorker extends HttpInterceptorWorker {
|
|
|
210
210
|
private async createResponseForRequest(request: HttpRequest) {
|
|
211
211
|
const methodHandlers = this.httpHandlersByMethod[request.method as HttpMethod];
|
|
212
212
|
|
|
213
|
-
const requestURL =
|
|
213
|
+
const requestURL = excludeNonPathParams(new URL(request.url));
|
|
214
214
|
const requestURLAsString = requestURL.href === `${requestURL.origin}/` ? requestURL.origin : requestURL.href;
|
|
215
215
|
|
|
216
216
|
for (let handlerIndex = methodHandlers.length - 1; handlerIndex >= 0; handlerIndex--) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { normalizeNodeRequest, sendNodeResponse } from '@whatwg-node/server';
|
|
2
2
|
import { HttpRequest, HttpMethod } from '@zimic/http';
|
|
3
3
|
import createRegexFromPath from '@zimic/utils/url/createRegexFromPath';
|
|
4
|
-
import
|
|
4
|
+
import excludeNonPathParams from '@zimic/utils/url/excludeNonPathParams';
|
|
5
5
|
import { createServer, Server as HttpServer, IncomingMessage, ServerResponse } from 'http';
|
|
6
6
|
import type { WebSocket as Socket } from 'isomorphic-ws';
|
|
7
7
|
|
|
@@ -314,7 +314,7 @@ class InterceptorServer implements PublicInterceptorServer {
|
|
|
314
314
|
private async createResponseForRequest(request: SerializedHttpRequest) {
|
|
315
315
|
const methodHandlers = this.httpHandlersByMethod[request.method as HttpMethod];
|
|
316
316
|
|
|
317
|
-
const requestURL =
|
|
317
|
+
const requestURL = excludeNonPathParams(new URL(request.url));
|
|
318
318
|
const requestURLAsString = requestURL.href === `${requestURL.origin}/` ? requestURL.origin : requestURL.href;
|
|
319
319
|
|
|
320
320
|
let matchedSomeInterceptor = false;
|