NextJs CORS issue
Asked Answered
B

19

71

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?

Bytom answered 29/11, 2020 at 9:20 Comment(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.Clothilde
@Clothilde 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 logicBytom
The crazy thing on my side is it does authentication but fails to fetch other dataEbner
B
72

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*',
          },
        ]
      },
  };
Bytom answered 29/11, 2020 at 9:58 Comment(5)
I got the answer and it works. But why exactly is this happening on NextJS?Vanburen
It does not work on Vercel. Any clue why?Vanburen
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.Bytom
You'll need to add the same config to vercel.json too: vercel.com/support/articles/…Chacha
I cannot make use of that solution because in POST requests body is not send, can anybody help?Counterfeit
M
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!' });
}
Metcalf answered 19/8, 2021 at 0:56 Comment(0)
J
15

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)
  }
Judie answered 21/4, 2021 at 18:31 Comment(5)
in my case const resp = await axios.get('dominio.com/xxx') res.status(200).json(resp.data)Ichnography
This trick working on my end . Thank you so much Bro for saving my timeRizas
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.Misconception
Is this when deployed on vercel?Bureaucracy
Hi @Bureaucracy No, not in Vercel.Judie
A
15

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();
});
Anabantid answered 7/6, 2021 at 17:34 Comment(0)
L
6

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

Lyle answered 29/1, 2022 at 20:11 Comment(2)
I had an extra '/' before my query string that botched it all. :joy: ty!Capps
That was my issue as well, thanks!Severally
C
3

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.

Chord answered 2/3, 2023 at 12:26 Comment(1)
In what file did you place your first snippet of handler code?Biography
A
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.

Ascending answered 17/6, 2022 at 18:4 Comment(0)
P
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.

Plataea answered 25/6, 2021 at 17:12 Comment(1)
It clearly stated that they are having next cors issues. 400 status code cant be related to CORs issue especially next with issues with corsGiovanna
H
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

Honebein answered 8/12, 2022 at 9:49 Comment(0)
T
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.

Torture answered 27/4, 2023 at 10:32 Comment(0)
S
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

Staff answered 16/6, 2023 at 10:2 Comment(0)
O
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
Obsolesce answered 31/1 at 17:8 Comment(0)
M
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.
Margenemargent answered 21/3 at 20:53 Comment(0)
S
0

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

Sitar answered 11/5 at 13:6 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Jaella
M
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

Mcvay answered 11/7 at 14:29 Comment(0)
A
-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.

Appoint answered 8/5, 2022 at 17:28 Comment(1)
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.Jaella
R
-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();
Reminiscence answered 19/2, 2023 at 3:37 Comment(0)
M
-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();
Mcgraw answered 12/6, 2023 at 13:29 Comment(0)
L
-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.

Ladon answered 8/9, 2023 at 17:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.