Search code examples
axiosnext.jspreflight

Next.js dynamic api pages fail to respond to post requests with Content-Type=application/json headers


I've got a next.js react app running on a custom Express server with custom routes. I'm working on this project by myself, but I'm hoping I might have a collaborator at some point, and so my main goal is really just to clean things up and make everything more legible.

As such, I've been trying move as much of the Express routing logic as possible to the built in Next.js api routes. I'm also trying to replace all the fetch calls I have with axios requests, since they look less verbose.

// current code
const data = await fetch("/api/endpoint", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ foo: "bar" })
}).then(x => x.json());

// what I'd like
const data = await axios.post( "/api/endpoint", { foo: "bar" });

The problem I've been having is that the dynamic next.js api routes stall as soon as there's JSON data in the body. I'm not even getting an error, the request just gets stuck as "pending" and the await promise never resolved.

I get responses from these calls, but I can't pass in the data I need:

// obviously no data passed
const data = await axios.post( "/api/endpoint");

// req.body = {"{ foo: 'bar' }":""}, which is weird
const data = await axios.post( "/api/endpoint", JSON.stringify({ foo: "bar" })); 

// req.body = "{ foo: 'bar' }" if headers omitted from fetch, so I could just JSON.parse here, but I'm trying to get away from fetch and possible parse errors
const data = await fetch("/api/endpoint", {
  method: "POST",
  // headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ foo: "bar" })
}).then(x => x.json()); 

If I try to call axios.post("api/auth/token", {token: "foo"}), the request just gets stuck as pending and is never resolved.

The Chrome Network panel gives me the following info for the stalled request:

General
  Request URL: http://localhost:3000/api/auth/token
  Referrer Policy: no-referrer-when-downgrade

Request Headers
  Accept: application/json, text/plain, */*
  Accept-Encoding: gzip, deflate, br
  Accept-Language: en-US,en;q=0.9,es;q=0.8
  Connection: keep-alive
  Content-Length: 26
  Content-Type: application/json;charset=UTF-8
  Cookie: token=xxxxxxxxxxxxxxxxxxxx; session=xxxxxxxxxxxxxxxxxxxxxxx
  Host: localhost:3000
  Origin: http://localhost:3000
  Referer: http://localhost:3000/dumbtest
  Sec-Fetch-Dest: empty
  Sec-Fetch-Mode: cors
  Sec-Fetch-Site: same-origin
  User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36

Request Payload
  {token: "foo"}

I've tried looking into what might be causing this, and everything seems to point towards there being an issue with preflight requests, but, since those are related to CORS policies, I don't understand why I'd be encountering those. I'm making a request from http://localhost:3000 to http://localhost:3000/api/auth/token.

Even so, I did try to add cors middleware as shown in the next.js example, but that didn't make a difference. As far as I can tell, the request never even hits the server - I've got a console.log call as the first line in the handler, but it's never triggered by these requests.

Is there something obvious I'm missing? This feels like it should be a simple switch to make, but I've spent the last day and a half trying to figure this out, but I keep reaching the same point with every solution I try - staring at a gray pending request in my Network tab and a console reporting no errors or anything.


Solution

  • After a few more hours searching, I found my answer here

    Turns out that since I was using a bodyParser middleware in my express server, I had to disable the Next body parsing by adding this at the top of my file:

    export const config = {
      api: {
        bodyParser: false,
      },
    }