Response patching is misbehave with FormData
Describe the bug
FormData was not sent alone with ctx.fetch(req), an empty object instead.
Environment
-
msw: 0.39.1 -
nodejs: 16.13.2 -
npm: 8.5.0 -
firefox: 97.0.1
To Reproduce
handler:
export const handlers = [
rest.post("/post", async (req, res, ctx) => {
console.log("msw body:", req.body);
const proxy = await ctx.fetch(req);
return res(
ctx.status(proxy.status),
ctx.body(await proxy.text())
);
}),
];
invoke:
const formData = new FormData();
formData.append("key", "value");
fetch("/post", { method: "POST", body: formData });
The original request has form data:

But request by msw has no form data:

Expected behavior
I'm expecting that ctx.fetch(req) behaves exact the same way as it without thourgh msw.
I'm not sure why this happens. Maybe fetch with content-type: multipart/form-data can't deal with plain object?
Sorry, I can not reproduce a precise fetch request to confirm my guessing.
FormData is converted to an plain object (see also issue-599): https://github.com/mswjs/msw/blob/0f0827c00d185533af258da8c0bb1285ab1f9b4c/src/context/fetch.ts#L29-L34
Hey, @QzCurious. Thanks for reporting this.
My hutch is that since the req (MockedRequest) instance always contains a text body, it attempts to send the text body when you perform ctx.fetch(req). This needs to be confirmed, though.
Why is the request/response body always text? So we could send it between the worker and the client threads (only text can be transmitted). It's also a natural shared denominator for variable request/response body types (text/Buffer/stream/FormData/Blob/etc.).
I'd be thankful for any help with investigating this 🙏
Hi, @kettanaito. Could you give me some hint how to test/debug a library like this one? What I it to be like:
- Setup up msw by go through with the doc
- Run a debugger (topically quokkajs/wallabyjs) to step through to see what steps that msw is doing from setting itself up to produce the mock
What I'm stuck is that service worker should be invoked by browser. I have no idea how do I load and initiate msw properly for the purpose of debugging (without browser).
@QzCurious, we don't have a built-in debugger as of now. This is something I'd like to add but it needs to be designed properly. I hope to get to this some time in the future.
What I'm stuck is that service worker should be invoked by browser. I have no idea how do I load and initiate msw properly for the purpose of debugging (without browser).
You still need browser, and you will be using browser to debug MSW in a browser anyway. Register the worker as you usually do. You can put debugger in the worker script and forcefully unregister the worker in "Applications > Service Workers" in your browser's DevTools. This will force the changes to the worker to take immediate effect.
The same applies to the library: it runs client-side as a part of your app, so you can go to its source and use debugger in relevant places (i.e. in src/context/fetch.ts, only its built *.js counterpart).
@kettanaito, you might misunderstood what I meant. I was not going to require a MSW debugger. I was looking for a way to investigate how MSW works. And then solve this issue and make a PR, hopefully.
I had run MSW with @msw/node with wallabyjs successfully. Will try the browser way that you state.
Hi @kettanaito, Congratulation for MSW v2. I thought this issue can be closed. With the new http handle I can read request.formData() without problem.
@QzCurious, thank you! This issue should've been marked as the one fixed by the 2.0 pull request. Closing it now.