Search code examples
javascriptexpressrestfetch-apiinsomnia

Express server doesn't receive body of PUT request from browser, but works for REST client


I've run into an immensely confusing situation. I am attempting to write some JavaScript code to perform a PUT request to my Express backend server, but even though I am absolutely certain that the requests are being sent correctly, the backend reports their request body as an empty object {}.

Here is a screenshot of the request error in Firefox, showing that it contains a valid request body: Screenshot of Firefox's request output

I get the same error in Chromium.

To investigate this, I tried sending the same request using my REST client (Insomnia). However, on copying the JSON body, I found that the request worked perfectly, as per this screenshot: Screenshot of Insomnia's request output

Here is what the route looks like on the backend:

app.put('/job/like', catchErrors(authed(async (req, res, authUserId) => {
  const { id, turnon } = req.body;
  console.log(req.body);
  /* do stuff */
  return res.status(200).send({});
})));

The console.log(req.body) produces {} for the request from Firefox, and the expected JSON object for the request from Insomnia.

Due to it being a university assignment, I cannot show my code that performs the request, but here is a console log of the request body on the browser's end.

{"id":865058,"turnon":false}

I am certain that this is sent correctly, as the same code works as expected for POST requests used elsewhere in the site.

I am performing this request, along with all others using the fetch API. All other requests I have tried have worked correctly.

I've been bug hunting this for a while now, but I can't find anything wrong with my code in a debugger or anything, and there doesn't seem to be any other cases of this happening to others that are documented on the internet (at least that I, as someone with 4 weeks of experience with frontend development can find).

I'd massively appreciate if anyone has any ideas why this might be happening, and/or how to fix it.


Solution

  • It turns out that when you include a headers: { Authorization: '...' } in your fetch call, it will change your content type back to plain text, rather than using JSON, which is what it does when you don't provide a header (the other routes were all login routes which didn't include a token). Express then silently deals with the fact that it got the wrong content type by replacing your plaintext JSON with an empty object.

    I was able to resolve this by including a 'Content-Type': 'application/json' field within my request header manually.