Search code examples
node.jsnext.jscors

How to handle OPTIONS request in nodejs when setting access control in header?


I need to set up a public API endpoint on a server running next.js. The code below works, I get the response without any CORS errors on the client side.

export default async (req, res) => {
  res.setHeader("Access-Control-Allow-Credentials", true);
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader(
    "Access-Control-Allow-Methods",
    "GET,OPTIONS,PATCH,DELETE,POST,PUT"
  );
  res.setHeader(
    "Access-Control-Allow-Headers",
    "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version"
  );

  try {
    switch (req.method) {
      case "OPTIONS": {
        res.send(200);
        break;
      }
      case "GET": {
        const response = "data";
        console.log("response in GET:", response);

        if (response != null) {
          res.status(200).json(response);
        }

        res.status(500).json({ error: "Something went wrong" });
        break;
      }
      default: {
        res.status(405).end("Method Not Allowed");
        break;
      }
    }
  } catch (error) {
    console.log(error);
    res.status(500).json({ error: "Something went wrong" });
  }
};

However, I do get an error on the server side:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

I'm not sure how to deal with this error, after all the code seems to work.

But what would be the proper way to do this, without getting this error?


Solution

  • Your problem is in the following code:

    case "GET": {
        const response = "data";
        console.log("response in GET:", response);
    
        if (response != null) {
          res.status(200).json(response);
        }
    
        res.status(500).json({ error: "Something went wrong" });
        break;
      }
    

    Here, if response != null, it will send the status 200 but then it will continue and also send the res.status(500). So it ends up sending 2 responses.

    To fix this, replace:

    if (response != null) {
        res.status(200).json(response);
    }
    

    with:

    if (response != null) {
        return res.status(200).json(response);
    }
    

    The key part here the return statement.