79

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?

3
  • 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. Commented Nov 29, 2020 at 9: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 Commented Nov 29, 2020 at 9:32
  • 1
    The crazy thing on my side is it does authentication but fails to fetch other data Commented Jul 12, 2021 at 9:53

20 Answers 20

79

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*',
          },
        ]
      },
  };
Sign up to request clarification or add additional context in comments.

5 Comments

I got the answer and it works. But why exactly is this happening on NextJS?
It does not work on Vercel. Any clue why?
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.
You'll need to add the same config to vercel.json too: vercel.com/support/articles/…
I cannot make use of that solution because in POST requests body is not send, can anybody help?
25

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!' });
}

Comments

17

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)
  }

5 Comments

in my case const resp = await axios.get('dominio.com/xxx') res.status(200).json(resp.data)
This trick working on my end . Thank you so much Bro for saving my time
that means you are making two requests instead of one. one for the next server and the other for API which does not make sense.
Is this when deployed on vercel?
Hi @m3.b No, not in Vercel.
16

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();
});

Comments

7

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

3 Comments

I had an extra '/' before my query string that botched it all. :joy: ty!
That was my issue as well, thanks!
I was using abc.com instead of www.abc.com, this was the issue.
4

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.

1 Comment

In what file did you place your first snippet of handler code?
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.

Comments

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.

1 Comment

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
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

Comments

0

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.

Comments

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

Comments

0

I was facing the, I was using Nextjs for FE and NodeJs, Express for BE. I use [cors][1] npm library to solve this issue in Nodejs

var cors = require('cors')
app.use(cors())
Use this code in app.js of NodeJS file [1]: https://expressjs.com/en/resources/middleware/cors.html

Comments

0

What helped me was to change the way of managing data fetching, when the error occurred, I performed the fetching from the client side, when I refactored the code to a fetching from the server side it worked without problems.

Previously

  • Page
// src/pages/home.js
import formServices from "@/services/test.service";

export default function PageHome({
 return (
 <div>
  <button onClick={()=>testService.getPing();}>PING</button>
 </div>
 );
})
  • Service
// src/services/test.service.js
import axios from "axios";
async function getPing() {
  const response = await axios.get("https://example.com/v2/api/ping");
  return await response.data;
}

const testServices = {
 getPing,
};

export default testServices;

Response

  • API Rest logs only returned code 204 at the OPTIONS request for preflight.
  • A response with code 307 Temporary Redirect appears in the browser.

Refactoring

  • Page
// src/pages/home.js
import formServices from "@/services/test.service";

export default function PageHome({
 return (
 <div>
  <button onClick={()=>testService.getPing();}>PING</button>
 </div>
 );
})
  • Service
// src/services/test.service.js
import axios from "axios";
async function getPing() {
  const response = await axios.get("/api/ping"); // get request to API Routes of NextJS
  return await response.data;
}

const testServices = {
 getPing,
};

export default testServices;
  • API Route
// src/app/api/ping/route.js
import { NextResponse } from "next/server";
import axios from "axios";
export async function GET() {
  const response = await axios.get("https://example.com/v2/api/ping").then((res) => {
    return res.data;
  });
  return NextResponse.json(response);
}

Response

  • Rest logs API returns code 204 for OPTIONS and 200 for GET request.
  • In the browser it looks like code 204 for OPTIONS and 200 for the GET request response.

Comments

0

I resolve it by adding Access-Control-Allow-Origin header in ningx configuration file

Comments

0

For me too the only way in which it worked was to enable it through vercel.json as per this article vercel docs.

I use next.js v 14.2.4

Hope it helps some other too

Comments

0

In Next.js 15 below worked for me, even in POST requests as well.

import { NextResponse } from 'next/server';

import type { NextMiddleware } from 'next/server';

const corsOptions = {
  allowedMethods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE', 'OPTIONS'],
  allowedOrigins: ['http://localhost:3000', '<your staging website>'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  exposedHeaders: [],
  maxAge: '86400', // 60 * 60 * 24 = 24hr
  credentials: 'true',
};

export const middleware: NextMiddleware = async (request) => {
  const response = NextResponse.next();

  const origin = request.headers.get('origin') ?? '';
  if (corsOptions.allowedOrigins.includes('*') || corsOptions.allowedOrigins.includes(origin)) {
    response.headers.set('Access-Control-Allow-Origin', origin);
  }

  response.headers.set('Access-Control-Allow-Credentials', corsOptions.credentials);
  response.headers.set('Access-Control-Allow-Methods', corsOptions.allowedMethods.join(','));
  response.headers.set('Access-Control-Allow-Headers', corsOptions.allowedHeaders.join(','));
  response.headers.set('Access-Control-Expose-Headers', corsOptions.exposedHeaders.join(','));
  response.headers.set('Access-Control-Max-Age', corsOptions.maxAge);

  return response;
};

export const config = {
  matcher: '/api/:path*',
};

Note: Please check your request headers and add the left one accordingly in the above code.

Github: https://github.com/vercel/next.js/discussions/47933#discussioncomment-12469914

Comments

-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.

1 Comment

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.
-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();

Comments

-2

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();

Comments

-2

for anyone using .NET 6 and facing this issue -> I used app.UseCors(e=>e.AllowAnyOrigin()); in Program.cs and i could resolve the issue.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.