Reputation: 4287
Was making a network call in getStaticProps
to APIs of superhero.com
which worked but when I tried making the same in useEffect
it is throwing CORS error.
Access to fetch at 'https://superheroapi.com/api//1' from origin 'http://localhost:3000' has been blocked by CORS policy: 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 have tried making network calls using fetch as well as axios but getting the same error. Does the problem or limitation lie with Next.js?
Edit: Tried using JSON placeholder APIs in useEffect
and it is working.
Upvotes: 10
Views: 22552
Reputation: 19
You must run your code on a domain that is validated. Some api give you cors error for localhost request.
Simple way is: Try to define a local domain (Change your local dns for that domain to 127.0.0.1 in host file) and write a server.js file like this. Replace 'next.yourdomain.com' with your domain ;)
const { createServer, } = require('http');
const { parse, } = require('url');
const next = require('next');
// const dev = process.env.NODE_ENV !== 'production';
const dev = false;
const app = next({dev, });
const handle = app.getRequestHandler();
const HOST = 'next.yourdomain.com';
const PORT = 8090;
app.prepare().then(() => {
createServer((req, res) => {
// Be sure to pass `true` as the second argument to `url.parse`.
// This tells it to parse the query portion of the URL.
const parsedUrl = parse(req.url, true);
handle(req, res, parsedUrl);
}).listen(PORT, HOST, (err) => {
if (err) throw err;
console.log(`Starting Next.js at http://${HOST}:${PORT}`);
});
});
Then run
next build && node server.js
Also you must discard this file on your final deploy.
Upvotes: 1
Reputation: 6362
CORS errors happen when you're trying to access resources from one domain on another domain. It only happens in the browser, and is a security feature.
So essentially, when you're fetching data from https://superheroapi.com/api/1
while on localhost:3000
, the browser first asks superheroapi.com
, "hey, can this domain fetch data from you?". superheroapi.com
will then say, "I only accept requests from these domains". If localhost:3000
is not in that list, you'll get a CORS error.
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
You can change the domains that superheroapi.com
accepts via the Access-Control-Allow-Origin
header. You can do it manually, or there's a handy npm package that will take care of that for you in Next.js.
By default in Next.js, the CORS header is restricted to same-domain traffic only. However, you can change this.
Next.js actually has a guide in their docs on adding a CORS header to api routes.
https://nextjs.org/docs/api-routes/api-middlewares#connectexpress-middleware-support
In short, though, first install the CORS package.
npm i cors
# or
yarn add cors
# or
pnpm add cors
Then add it to the API route.
import Cors from 'cors'
// Initializing the cors middleware
const cors = Cors({
methods: ['GET', 'HEAD'],
})
// Helper method to wait for a middleware to execute before continuing
// And to throw an error when an error happens in a middleware
function runMiddleware(req, res, fn) {
return new Promise((resolve, reject) => {
fn(req, res, (result) => {
if (result instanceof Error) {
return reject(result)
}
return resolve(result)
})
})
}
async function handler(req, res) {
// Run the middleware
await runMiddleware(req, res, cors)
// Rest of the API logic
res.json({ message: 'Hello Everyone!' })
}
export default handler
Code snippets are taken from the Next.js docs. All credit goes to the makers of Next.js for them.
Upvotes: 10
Reputation: 3020
Code in useEffect
runs in the frontend/browser therefore must obey the CORS. getStaticProps
runs at build time, therefore do not have the CORS limitation.
If superheroapi.com API is under your control, you should add CORS response headers to fix the issue. Otherwise you need to create a reverse proxy, e.g., https://www.npmjs.com/package/cors-anywhere
Upvotes: 3