@zimic/interceptor 1.2.7-canary.2 → 1.3.0-canary.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.
package/dist/http.js CHANGED
@@ -1069,6 +1069,7 @@ var DEFAULT_UNHANDLED_REQUEST_STRATEGY = Object.freeze({
1069
1069
  });
1070
1070
 
1071
1071
  // src/http/interceptorWorker/HttpInterceptorWorker.ts
1072
+ var RESPONSE_ACTION_SYMBOL = Symbol.for("HttpResponse.action");
1072
1073
  var HttpInterceptorWorker = class _HttpInterceptorWorker {
1073
1074
  platform = null;
1074
1075
  isRunning = false;
@@ -1165,17 +1166,57 @@ var HttpInterceptorWorker = class _HttpInterceptorWorker {
1165
1166
  }
1166
1167
  return interceptor.onUnhandledRequest;
1167
1168
  }
1168
- static createResponseFromDeclaration(request, declaration) {
1169
+ static setResponseAction(response, action) {
1170
+ Object.defineProperty(response, RESPONSE_ACTION_SYMBOL, {
1171
+ value: action,
1172
+ enumerable: false,
1173
+ configurable: false,
1174
+ writable: false
1175
+ });
1176
+ }
1177
+ static getResponseAction(response) {
1178
+ if (!(RESPONSE_ACTION_SYMBOL in response)) {
1179
+ return void 0;
1180
+ }
1181
+ const action = response[RESPONSE_ACTION_SYMBOL];
1182
+ if (action !== "bypass" && action !== "reject") {
1183
+ return void 0;
1184
+ }
1185
+ return action;
1186
+ }
1187
+ createBypassedResponse() {
1188
+ const response = Response.redirect("about:blank", 302);
1189
+ _HttpInterceptorWorker.setResponseAction(response, "bypass");
1190
+ return response;
1191
+ }
1192
+ static isBypassedResponse(response) {
1193
+ return this.getResponseAction(response) === "bypass";
1194
+ }
1195
+ createRejectedResponse() {
1196
+ const response = Response.error();
1197
+ _HttpInterceptorWorker.setResponseAction(response, "reject");
1198
+ return response;
1199
+ }
1200
+ static isRejectedResponse(response) {
1201
+ return this.getResponseAction(response) === "reject";
1202
+ }
1203
+ createResponseFromDeclaration(request, declaration) {
1204
+ if ("action" in declaration) {
1205
+ if (declaration.action === "bypass") {
1206
+ return this.createBypassedResponse();
1207
+ } else {
1208
+ return this.createRejectedResponse();
1209
+ }
1210
+ }
1169
1211
  const headers = new http.HttpHeaders(declaration.headers);
1170
- const status = declaration.status;
1171
- const canHaveBody = methodCanHaveResponseBody(request.method) && status !== 204;
1212
+ const canHaveBody = methodCanHaveResponseBody(request.method) && declaration.status !== 204;
1172
1213
  if (!canHaveBody) {
1173
- return new Response(null, { headers, status });
1214
+ return new Response(null, { headers, status: declaration.status });
1174
1215
  }
1175
1216
  if (typeof declaration.body === "string" || declaration.body === null || declaration.body === void 0 || declaration.body instanceof FormData || declaration.body instanceof URLSearchParams || declaration.body instanceof Blob || declaration.body instanceof ArrayBuffer || declaration.body instanceof ReadableStream) {
1176
- return new Response(declaration.body ?? null, { headers, status });
1217
+ return new Response(declaration.body ?? null, { headers, status: declaration.status });
1177
1218
  }
1178
- return Response.json(declaration.body, { headers, status });
1219
+ return Response.json(declaration.body, { headers, status: declaration.status });
1179
1220
  }
1180
1221
  static async parseRawUnhandledRequest(request) {
1181
1222
  return this.parseRawRequest(
@@ -1604,8 +1645,9 @@ var HttpInterceptorClient = class {
1604
1645
  if (!responseDeclaration) {
1605
1646
  return null;
1606
1647
  }
1607
- const response = HttpInterceptorWorker_default.createResponseFromDeclaration(request, responseDeclaration);
1608
- if (this.requestSaving.enabled) {
1648
+ const response = await this.workerOrThrow.createResponseFromDeclaration(request, responseDeclaration);
1649
+ const shouldSaveInterceptedRequest = this.requestSaving.enabled && response && !HttpInterceptorWorker_default.isRejectedResponse(response);
1650
+ if (shouldSaveInterceptedRequest) {
1609
1651
  const responseClone = response.clone();
1610
1652
  const parsedResponse = await HttpInterceptorWorker_default.parseRawResponse(responseClone);
1611
1653
  matchedHandler.saveInterceptedRequest(parsedRequest, parsedResponse);
@@ -1822,7 +1864,7 @@ var LocalHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
1822
1864
  const requestClone = request.clone();
1823
1865
  let response = null;
1824
1866
  try {
1825
- response = await createResponse({ ...context, request });
1867
+ response = await createResponse({ request });
1826
1868
  } catch (error) {
1827
1869
  console.error(error);
1828
1870
  }
@@ -1841,6 +1883,23 @@ var LocalHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
1841
1883
  };
1842
1884
  methodHandlers.push(handler);
1843
1885
  }
1886
+ async createResponseFromDeclaration(request, declaration) {
1887
+ const requestClone = request.clone();
1888
+ const response = await super.createResponseFromDeclaration(request, declaration);
1889
+ if (response && HttpInterceptorWorker_default.isBypassedResponse(response)) {
1890
+ try {
1891
+ const response2 = await fetch(msw.bypass(requestClone));
1892
+ return response2;
1893
+ } catch (error) {
1894
+ console.error(error);
1895
+ return null;
1896
+ }
1897
+ }
1898
+ if (response && HttpInterceptorWorker_default.isRejectedResponse(response)) {
1899
+ return response;
1900
+ }
1901
+ return response;
1902
+ }
1844
1903
  async createResponseForRequest(request) {
1845
1904
  const methodHandlers = this.httpHandlersByMethod[request.method];
1846
1905
  const requestURL = excludeNonPathParams_default(new URL(request.url));
@@ -1898,6 +1957,17 @@ var LocalHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
1898
1957
  };
1899
1958
  var LocalHttpInterceptorWorker_default = LocalHttpInterceptorWorker;
1900
1959
 
1960
+ // src/server/errors/UnsupportedResponseBypassError.ts
1961
+ var UnsupportedResponseBypassError = class extends Error {
1962
+ constructor() {
1963
+ super(
1964
+ "Remote interceptors cannot bypass responses. Use `{ action: 'reject' }` instead.\n\nLearn more: https://zimic.dev/docs/interceptor/api/http-request-handler#handlerrespond"
1965
+ );
1966
+ this.name = "UnsupportedResponseBypassError";
1967
+ }
1968
+ };
1969
+ var UnsupportedResponseBypassError_default = UnsupportedResponseBypassError;
1970
+
1901
1971
  // src/utils/crypto.ts
1902
1972
  var importCrypto = createCachedDynamicImport_default(async () => {
1903
1973
  const globalCrypto = globalThis.crypto;
@@ -1925,6 +1995,8 @@ async function serializeResponse(response) {
1925
1995
  const responseClone = response.clone();
1926
1996
  const serializedBody = responseClone.body ? convertArrayBufferToBase64(await responseClone.arrayBuffer()) : null;
1927
1997
  return {
1998
+ type: response.type,
1999
+ action: HttpInterceptorWorker_default.getResponseAction(response),
1928
2000
  status: response.status,
1929
2001
  statusText: response.statusText,
1930
2002
  headers: Object.fromEntries(response.headers),
@@ -2401,8 +2473,8 @@ var RemoteHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
2401
2473
  const request = deserializeRequest(serializedRequest);
2402
2474
  try {
2403
2475
  const rawResponse = await handler?.createResponse({ request }) ?? null;
2404
- const response = rawResponse && request.method === "HEAD" ? new Response(null, rawResponse) : rawResponse;
2405
- if (response) {
2476
+ if (rawResponse) {
2477
+ const response = methodCanHaveResponseBody(request.method) ? rawResponse : new Response(null, rawResponse);
2406
2478
  return { response: await serializeResponse(response) };
2407
2479
  }
2408
2480
  } catch (error) {
@@ -2449,10 +2521,7 @@ var RemoteHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
2449
2521
  method,
2450
2522
  path,
2451
2523
  interceptor,
2452
- async createResponse(context) {
2453
- const response = await createResponse(context);
2454
- return response;
2455
- }
2524
+ createResponse
2456
2525
  };
2457
2526
  this.httpHandlers.set(handler.id, handler);
2458
2527
  await this.webSocketClient.request("interceptors/workers/commit", {
@@ -2462,6 +2531,16 @@ var RemoteHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
2462
2531
  path: handler.path
2463
2532
  });
2464
2533
  }
2534
+ async createResponseFromDeclaration(request, declaration) {
2535
+ const response = await super.createResponseFromDeclaration(request, declaration);
2536
+ if (response && HttpInterceptorWorker_default.isBypassedResponse(response)) {
2537
+ throw new UnsupportedResponseBypassError_default();
2538
+ }
2539
+ if (response && HttpInterceptorWorker_default.isRejectedResponse(response)) {
2540
+ return response;
2541
+ }
2542
+ return response;
2543
+ }
2465
2544
  async clearHandlers(options = {}) {
2466
2545
  if (!this.isRunning) {
2467
2546
  throw new NotRunningHttpInterceptorError_default();
@@ -2821,6 +2900,8 @@ var InvalidFormDataError = class extends http.InvalidFormDataError {
2821
2900
  };
2822
2901
  var InvalidJSONError = class extends http.InvalidJSONError {
2823
2902
  };
2903
+ /* istanbul ignore if -- @preserve
2904
+ * This is just a type guard to ensure the value is valid. In practice, this condition should never be true. */
2824
2905
  /* istanbul ignore next -- @preserve
2825
2906
  * Ignoring because there will always be a handler for the given method and path at this point. */
2826
2907
  /* istanbul ignore if -- @preserve