mswjs / msw

Industry standard API mocking for JavaScript.
https://mswjs.io
MIT License
15.97k stars 519 forks source link

Disabling "navigate" bypass causes TypeError: "Uncaught (in promise) TypeError: Failed to construct 'Request': Cannot construct a Request with a RequestInit whose mode member is set as 'navigate'." #2229

Open iulspop opened 3 months ago

iulspop commented 3 months ago

Prerequisites

Environment check

Browsers

Chromium (Chrome, Brave, etc.), Firefox, Safari

Reproduction repository

https://github.com/iulspop/msw-navigate-error

Reproduction steps

  1. npm install
  2. npm run dev
  3. Go to localhost:5173
  4. Click link to /api/auth/login

Current behavior

On Chrome

When the handler runs it throws this uncaught error:

parseWorkerRequest.ts:11 Uncaught (in promise) TypeError: Failed to construct 'Request': Cannot construct a Request with a RequestInit whose mode member is set as 'navigate'.
    at parseWorkerRequest (parseWorkerRequest.ts:11:10)
    at createRequestListener.ts:31:21
    at ServiceWorkerContainer.<anonymous> (setupWorker.ts:84:15)

at parseWorkerRequest.ts:

/**
 * Converts a given request received from the Service Worker
 * into a Fetch `Request` instance.
 */
export function parseWorkerRequest(
  incomingRequest: ServiceWorkerIncomingRequest,
): Request {
  return new Request(incomingRequest.url, {
    ...incomingRequest,
    body: pruneGetRequestBody(incomingRequest),
  })
}

On Safari

Navigates to http://localhost:5173/api/auth/login and responds 200 OK with index.html body. Seems like worker doesn't run at all because it should print when intercepting request, maybe navigate GET requests aren't intercepted by service workers on Safari and Firefox? mockServiceWorker.js

self.addEventListener('fetch', function (event) {
  const { request } = event

  if (request.mode === 'navigate' && (request.url.includes('/api/auth/login'))) {
    console.log('request.mode: ', request.mode, 'request.url: ', request.url);
  }

  // Bypass navigation requests.
  if (request.mode === 'navigate' && !request.url.includes('/api/auth/login')) {
    return
  }

On Firefox

Same as Safari

Expected behavior

For the request handler defined for api/auth/login to respond with 302 and redirect / and set the cookie.