msw
msw copied to clipboard
v2.2.2 does not intercept request in browser mode (CORS error) but v1.3.1 does
Prerequisites
- [X] I confirm my issue is not in the opened issues
- [X] I confirm the Frequently Asked Questions didn't contain the answer to my issue
Environment check
- [X] I'm using the latest
msw
version - [X] I'm using Node.js version 18 or higher
Browsers
Chromium (Chrome, Brave, etc.), Firefox
Reproduction repository
https://github.com/somewonderfulguy/timeline
Node.js version
20.11.1
Reproduction steps
To reproduce the issue you need to clone minimal project with only one request.
This will clone & launch the app using MSW 1.3.1 there, you'll see that everything works as expected:
git clone https://github.com/somewonderfulguy/timeline.git
cd ./timeline
pnpm i
pnpm dev-offline
Then, switching to 2.2.2:
git checkout msw-v2
pnpm i
pnpm dev-offline
The request is not going to pass now. It will have strict-origin-when-cross-origin
error.
Last week I added MSW to CRA project (MSW was 2.2.1) and worked fine to me. Today, I decided to bootstrap new project using Vite and it doesn't work. Downgrading to 2.2.1 doesn't help, downgrading to 1.3.1 does.
Current behavior
Vite@5 and MSW@2 do not mix - CORS error happens.
Expected behavior
MSW 2 requests interception should work with Vite.
UPDATE: As I continue to investigate, it seems like Vite is not an issue. I checked CRA and see there's the same error actually. It worked for me because the real endpoint exists. However if you try to intercept completely made up URL, then the issue happens.
I do hope I haven't spammed a duplicate. However, I couldn't find similar issue and the only fix that worked to me is to do a major downgrade.
Hi, @somewonderfulguy. Thanks for reporting this.
Can you please include the actual CORS error too?
Note that you are comparing versions of MSW that are about a year apart (1.3 and 2.x). I'm not aware of any issues in MSW that would cause a CORS error, unless you are indeed violating the CORS policy (that indicates an invalid request). That's why I'm curious to see the error message.
Hi, @kettanaito!
I don't suppose I have an invalid request. Not sure. I mean, absolutely the same request is intercepted in v1.3 without CORS. Change the version - you'll get error.
I forgot to mention that in the repository I left in issue description there's a branch msw-v2. And the master branch has v1.3. So it is possible to try both branches. They are absolutely identical but the msw version and, of course, msw syntax and different mockServiceWorker.js
in public
directory.
The error here. Nothing in response tab:
The request.ts:24
stands for:
// ...
if (body) config.body = isFormData ? body : JSON.stringify(body)
return fetch(endpoint, config).then(async (response) => {
// request.ts:24 ^^^^^^^^
let data
// ...
Hi, @somewonderfulguy. I looked into this issue and discovered the root cause for this behavior.
Root cause
Here, you are setting the baseUrl
incorrectly:
const version = 'v1';
export const baseUrl = `http://localhost/api/${version}`;
The base is http://localhost
while your app is running at http://localhost:5173
. That means that the request will be cross-origin, and by default, it will be aborted. That's precisely what happens:
GET http://localhost/api/v1/editorData net::ERR_CONNECTION_REFUSED
Moreover, since the base URL is invalid, you are fetching a resource that doesn't exist.
How to fix this
First, define the correct baseUrl
. I recommend using the URL
constructor and document.baseURI
as the base URL.
Once you do, you will discover the /api/v1/editorData
returning 304 with the page's HTML instead of the mock data. That's because you aren't awaiting the worker.start()
Promise.
Here's a complete diff you can apply to fix your problem:
index e283784..39220cf 100644
--- a/src/api/baseUrl.ts
+++ b/src/api/baseUrl.ts
@@ -1,2 +1,2 @@
const version = 'v1';
-export const baseUrl = `http://localhost/api/${version}`;
+export const baseUrl = new URL(`/api/${version}`, document.baseURI);
diff --git a/src/main.tsx b/src/main.tsx
index 9469f4a..8da9ea2 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -17,7 +17,7 @@ const launchOffline = async () => {
await import('../public/mockServiceWorker.js?worker');
- importResult.worker.start({
+ await importResult.worker.start({
onUnhandledRequest: 'bypass'
});
};
order.api.ts:6 GET http://localhost:3000/orders 404 (Not Found)
export const handlers = [
http.get("/orders", ({ params }) => {
const { orderId } = params;
return HttpResponse.json({
id: orderId,
productIds: ["10055045842720", "10055045842721", "10055045842722"],
totalAmount: 100.5,
status: "1",
createdAt: "2024-09-23T10:34:56Z",
});
}),
];
@zhishaofei3, you are fetching /orders
while expecting params.orderId
to exist in the resolver? That looks broken to me. Either adjust the path to be http.get('/orders/:orderId')
or drop the access to params.orderId
.
If something doesn't work right, follow the Debugging runbook.