51

I have a Next.js app hosted on Vercel at www.example.com, which needs to communicate with a backend .NET Core Web API hosted on a different server at api.example.com. The .NET core web api has been configured to allow CORS but my Next.js keeps complaining that data cannot be displayed when I use AXIOS to fetch data because the response lacks allow-cors headers:

Access to XMLHttpRequest at 'https://api.example.com' from origin 'http://www.example.com' 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

It works fine when I run it locally using npm run dev, but doesn't work when I build it and then run npm run start

Does anyone know how to fix the cors issue in production?

Yoope
  • 1,745
  • 2
  • 16
  • 22
  • Can you clarify what you mean when you say that the server is “configured to allow CORS”? Seems like your backend isn’t allow-listing your frontend. – JBallin Nov 29 '20 at 09:24
  • 2
    @JBallin The .NET Core Web API uses .UseCors middleware to allow CORS access. The back-end appears to be working fine because I also have a React App created using create-react-app and served as static file. That app is able to communicate with my backend just fine. I assume the problem here has something to do with the Next.Js server side logic – Yoope Nov 29 '20 at 09:32
  • 1
    The crazy thing on my side is it does authentication but fails to fetch other data – emanuel sanga Jul 12 '21 at 09:53

14 Answers14

64

I found a solution here:

Basically, I just need to add a next.config.js file in the root directory and add the following:

// next.config.js
module.exports = {
    async rewrites() {
        return [
          {
            source: '/api/:path*',
            destination: 'https://api.example.com/:path*',
          },
        ]
      },
  };
Joel
  • 5,732
  • 4
  • 37
  • 65
Yoope
  • 1,745
  • 2
  • 16
  • 22
  • 2
    I got the answer and it works. But why exactly is this happening on NextJS? – Y M Sep 02 '21 at 06:54
  • 4
    It does not work on Vercel. Any clue why? – Y M Sep 06 '21 at 11:49
  • 1
    I thnk what happens here is that this config will be passed to the next.js server to proxy all calls to example.com/api to api.example.com. It should work on Vercel as I deployed my app there and it seems to work fine. – Yoope Sep 08 '21 at 12:01
  • 2
    You'll need to add the same config to vercel.json too: https://vercel.com/support/articles/how-to-enable-cors#enabling-cors-using-vercel.json – martinedwards Sep 27 '21 at 15:21
  • 1
    I cannot make use of that solution because in POST requests body is not send, can anybody help? – Kostya Tresko Jun 26 '22 at 12:54
20

if you want to use the cors library in nextjs, I created a library for it is nextjs-cors.

https://www.npmjs.com/nextjs-cors

https://github.com/yonycalsin/nextjs-cors

pages/api/whoami.{ts,js}

import NextCors from 'nextjs-cors';

async function handler(req, res) {
   // Run the cors middleware
   // nextjs-cors uses the cors package, so we invite you to check the documentation https://github.com/expressjs/cors
   await NextCors(req, res, {
      // Options
      methods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'],
      origin: '*',
      optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
   });

   // Rest of the API logic
   res.json({ message: 'Hello NextJs Cors!' });
}
Yony Calsin
  • 235
  • 2
  • 3
14

it was a problem in the server not accepting OPTIONS requests, because routes were declared as GET::something or POST:: something, so the preflight couldn't pass and the POST request was decliend, hope this will help another people to prevent hours of googling, so in my case (Node.js + Express.js) i had to add this to my server.js

  app.use((req, res, next) => {
    res.header("Access-Control-Allow-Origin", "*");
    res.header(
      "Access-Control-Allow-Headers",
      "Origin, X-Requested-With, Content-Type, Accept, Authorization"
    );
  if (req.method == "OPTIONS") {
    res.header("Access-Control-Allow-Methods", "PUT, POST, PATCH, DELETE, GET");
    return res.status(200).json({});
  }

  next();
});
Abdul Saleem
  • 10,098
  • 5
  • 45
  • 45
hamdi islam
  • 1,327
  • 14
  • 26
9

I had a similar issue, I was making the call from this page:

pages/page1.js

  export default async function page1() {
       const data = await axios.post('https://www.dominio.com/xxx' , {param: 1}, headers)
}

But the solution is to make axios calls to a local API file inside "pages/api" directory, and this local API file, will handle the request to the external webserver. This avoid the CORS issue.

pages/page1.js

export default async function page1() {
        const data = await axios.post('/api/get_page1_data', {param: 1} )
}

pages/api/get_page1_data.js

export default async function handler(req, res) {
try{
   const data = await axios.post('https://www.dominio.com/xxx' , {param: req.body.param}, headers)
    res.status(200).json(data)
 } catch (error) {
    console.error(error)
    return res.status(error.status || 500).end(error.message)
  }
chispitaos
  • 767
  • 9
  • 14
3

Do an extra check if your base URL is correct that was my issue

2

In my case, the preflight request was failing due to an agressive HTTP method filter.

Make sure that you specify

  // Preflight Check:
  if (req.method == "OPTIONS") {
    res.setHeader("Allow", "POST");
    return res.status(202).json({});
  }

  // Allow only POST Methods 
  if (req.method !== "POST") {
    res.setHeader("Allow", "POST");
    return res.status(405).json({ error: `Method ${req.method} Not Allowed` });
  }

You can allow all methods with https://vercel.com/support/articles/how-to-enable-cors#enabling-cors-in-a-next.js-app, but make sure that each endpoint returns a 2XX status code for the OPTIONS HTTP method.

1

After many research, I finally find the answer, there are two ways of doing it, if you are not hosted in vercel:

const cors = require('cors');

const corsOptions = {
  origin: 'https://example.com',
  methods: ['GET', 'POST'],
  allowedHeaders: ['Content-Type'],
  optionsSuccessStatus: 200,
};

export default function handler(req, res) {
  cors(corsOptions)(req, res, () => {
    // Your API code here
    res.status(200).json({ message: 'Hello, World!' });
  });
}

Alternatively, you can use https://www.npmjs.com/nextjs-cors as mentioned in the previous post, which is similar with this method.

If you are hosting on vercel (refer to doc here):

  1. In the root directory of your project, create a file named vercel.json.
  2. Add the following code to the vercel.json file:
{
  "headers": [
    {
      "source": "/api/(.*)",
      "headers": [
        { "key": "Access-Control-Allow-Credentials", "value": "true" },
        { "key": "Access-Control-Allow-Origin", "value": "*" },
        { "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" }
      ]
    }
  ]
}

After deploying your project, Vercel will automatically apply the CORS configuration defined in the vercel.json file to your API routes.

GSW
  • 21
  • 5
1

The issue in my case was that although I configured CORS in my .NET API, but I didn't register the CORS middleware, which your Next js app was trying to use.

So don't forget to add

app.UseCors();

when you configure your request pipeline (Configure method in the old startup.cs). This will add the necessary options endpoints.

fbede
  • 843
  • 9
  • 12
0

Please make sure it is CORS and is not something else. For example, in my case I was getting a 400 response. Please look on the Response tab of that request for information.

Gabriel Arghire
  • 1,992
  • 1
  • 21
  • 34
  • It clearly stated that they are having next cors issues. 400 status code cant be related to CORs issue especially next with issues with cors – Oyetoke Tobi Sep 07 '21 at 07:39
0

after hours of googleing i found the solution on the next-docs itself!!!

see the following repository on github

API Routes Example with CORS

https://github.com/vercel/next.js/tree/canary/examples/api-routes-cors

Ali Afzali
  • 109
  • 7
0

For my case the problem was I was making a request to http://127.0.0.1:3000 and my next js app was running on localhost:3000 this was raising the CORS issue. I only changed the request to be made to http://localhost:3000. So remember to check the base of your api endpoint otherwise that was my resolve

-1

I have Next.js application that has graphql and Apollo Client setup (apollo version : 3.5.10). In order to make a query inside any component you have to use "client" variable that Apollo Client provide. You need to have apollo-client.js file in your project root so that Apollo Client can use it inside any component for query. Inside any component when you trying to make a query like: client.query(...), with these settings of apollo-client file it will throw "cors" error. However you can fix this by adding headers property inside apollo-client file.

This is OLD Settings:

apollo-client.js (old)

import { ApolloClient, InMemoryCache } from '@apollo/client';

const client = new ApolloClient({
  uri: 'http://localhost:4000/graphql',
  cache: new InMemoryCache(),
});

export default client;

This is NEW Settings:

apollo-client.js (new)

import { ApolloClient, InMemoryCache } from '@apollo/client';

const client = new ApolloClient({
  uri: 'http://localhost:4000/graphql',
  cache: new InMemoryCache(),
  headers: {
    fetchOptions: {
      mode: 'no-cors',
    },
  },
});

export default client;

By doing this, you won't get any "cors" error while doing query inside any component.

jsUser
  • 1
  • 1
  • 2
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 08 '22 at 22:34
-1

I had this issue taking a SoloLearn NestJS course and it was resolved by adding the line: app.enableCors() in main.ts file on the root folder in the NESTJs Project. The file was like this:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableCors();
  await app.listen(3000);
}
bootstrap();
-1

On NEST JS, in your main.ts file

Do this

/* eslint-disable prettier/prettier */

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {

  const app = await NestFactory.create(AppModule);
  //Use this to remove cors errors from client side request
  app.use((req, res, next) => {
    res.header("Access-Control-Allow-Origin", "*");
    res.header(
      "Access-Control-Allow-Headers",
      "Origin, X-Requested-With, Content-Type, Accept, Authorization"
    );
    if (req.method == "OPTIONS") {
      res.header("Access-Control-Allow-Methods", "PUT, POST, PATCH, DELETE, GET");
      return res.status(200).json({});
    }
    next();
  });

  await app.listen(4000);
}
bootstrap();