msw icon indicating copy to clipboard operation
msw copied to clipboard

fix(multipart/form-data): Include form data in the request payload when making a proxy request with ctx.fetch(req)

Open MartinJaskulla opened this issue 2 years ago • 4 comments

Fixes https://github.com/mswjs/msw/issues/1158

When making a FormData request, the browser adds the content-type header automatically and adds a boundary e.g. "content-type": multipart/form-data; boundary=----WebKitFormBoundarygyGKnRF8C9LT0BhB".

const formData = new FormData();
formData.append("key", "value");
fetch("/post", { method: "POST", body: formData });

When this request is intercepted and proxied

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())
    );
  }),
];

and we are creating a new request in mockServiceWorker.js,

const originalRequest = new Request(requestClone, {
      headers: new Headers(cleanRequestHeaders),
})

then cleanRequestHeaders will have the property "content-type": multipart/form-data; boundary=----WebKitFormBoundarygyGKnRF8C9LT0BhB". The browser treats this as a user-provided header and does not add a new boundary value. This will break the body and no payload will be send. If we delete the content-type header, the browser will automatically re-add it with a new boundary value and the form data is included in the payload.

Solution found here: https://community.cloudflare.com/t/cannot-seem-to-send-multipart-form-data/163491/2

Notice the new boundary value: Screenshot 2022-04-04 at 08 45 07 Screenshot 2022-04-04 at 08 46 03

MartinJaskulla avatar Apr 03 '22 19:04 MartinJaskulla

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 3c887e492dab7cec1f3aca5898a4429b4f626678:

Sandbox Source
MSW React Configuration

codesandbox-ci[bot] avatar Apr 03 '22 19:04 codesandbox-ci[bot]

Hey, @MartinJaskulla. Thanks for opening this!

This is interesting. As I understand, the issue happens only when proxying requests with ctx.fetch. What do you think if we add this headers logic to that very function instead of the worker script?

Changes to the worker script are always breaking changes, as developers would have to update those on their machines to guarantee MSW works as expected (even if they're using an automatic update route). I'd much prefer for this to be tackled in the underlying API like ctx.fetch, especially if that's where the problem occurs.

Do you see any implications of moving this change to ctx.fetch?

kettanaito avatar Apr 03 '22 23:04 kettanaito

Makes sense. ctx.fetch seems like a much better place for this check. Also easier to unit test.

Will take a look tomorrow evening.

MartinJaskulla avatar Apr 03 '22 23:04 MartinJaskulla

Sounds fantastic! Thank you so much.

kettanaito avatar Apr 03 '22 23:04 kettanaito