Search code examples
javascriptherokunext.jscorsnetlify

Handling cors with next.js


I'm using netlify as my front end and heroku with Next.js as my backend

on the front end I'm sending a fetch request like this:

fetch(`https://backendname.herokuapp.com/data`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({"category":"_main"})
  }).then(...);

and in my pages/api/data.js in the backend:

export default function handler(req, res) {
    req.body=JSON.parse(req.body);

    res.setHeader("Access-Control-Allow-Origin", "https://frontendname.netlify.app/");
    res.setHeader('Access-Control-Allow-Methods', 'POST');
    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'
    )
    if(req.method!='POST')
     return res.end();

    res.json({...})

}

I even added this to my next.config.js:

module.exports = {
  async headers() {
    return [
      {
        // matching all API routes
        source: "/api/:path*",
        headers: [
          { key: "Access-Control-Allow-Credentials", value: "true" },
          { key: "Access-Control-Allow-Origin", value: "https://frontendname.netlify.app/" },
          { key: "Access-Control-Allow-Methods", value: "GET,OPTIONS,PATCH,DELETE,POST,PUT" },
          { key: "Access-Control-Allow-Headers", value: "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" },
        ]
      }
    ]
  },
  reactStrictMode: true,
}

but I get this error:

Access to fetch at 'https://backendname.herokuapp.com/data' from origin 'https://frontendname.netlify.app' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I'm trying not to use any third party packages like in this question


Solution

  • Problem(s)

    https://frontendname.netlify.app/ is not an origin. Because the CORS middleware observes a mismatch between

    • the actual origin of your request (https://frontendname.netlify.app), and
    • the "origin" that you've allowed in your CORS configuration (https://frontendname.netlify.app/),

    it doesn't set the Access-Control-Allow-Origin response header, which causes the preflight check to fail.

    You also seem to set CORS headers in multiple places, which isn't a good idea.

    Solution

    Drop that trailing slash in the value set in the Access-Control-Allow-Origin header, and don't specify duplicate CORS headers in the response.