I am having a problem with cors when I call my netlify hosted nodejs express backend from my react frontend.
im am getting the following errormessage in my web browser:
Access to XMLHttpRequest at 'https://<my_api_domain>/api/forgotpassword' from origin 'localhost:8888' has been blocked by CORS policy: No 'Access-
Control-Allow-Origin' header is present on the requested resource."
I have tried a lot of solutions with setting headers in the respons from my backend, but nothing seams to work. In localhost everything works fine.
the main file, api.js, looks like this:
'use strict';
const express = require('express');
const serverless = require('serverless-http');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
const router = express.Router();
router.use(express.json());
const apiLimiter = require('../middleware/ratelimiter');
//import modules
const youtube = require('./youtube');
const ip = require('./ip');
const sendgrid = require('./sendgrid');
const sendinblue = require('./sendinblue');
const login = require('./login');
const forgotPassword = require('./forgotpassword');
const register = require('./register');
const test = require('./test');
require('dotenv').config();
router.use(helmet());
router.use(morgan('combined'));
router.use(cors());
//this part was added in order to try to fix the cors error
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content, Accept, Content-Type, Authorization'
);
res.setHeader(
'Access-Control-Allow-Methods',
'GET, POST, PUT, DELETE, PATCH, OPTIONS'
);
next();
});
app.use(bodyParser.json());
router.use('/ip', ip);
router.use('/youtube', youtube);
router.use('/sendgrid', sendgrid);
router.use('/sendinblue', sendinblue);
router.use('/login', login);
router.use('/register', register);
router.use('/test', test);
router.use('/forgotpassword', forgotPassword);
app.use('/api', router);
// path must route to lambda
app.set('trust proxy', 1);
module.exports = app;
module.exports.handler = serverless(app);
The cors error only happens when I call the forgotpassword endpoint, which looks like this:
const express = require('express');
const router = express.Router();
//const { check, validationResult } = require('express-validator');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const connect = require('../functions/db');
const captcha = require('../middleware/captcha');
const sendMail = require('../functions/sendResetMail');
require('dotenv').config();
// get usermodel
const User = require('../models/User');
const Token = require('../models/resetPassword');
//#path: /forgotpassword
//# public
router.post(
'/',
captcha,
async (req, res) => {
const { email } = req.body.data;
console.log(email);
connect();
try {
// See if user exists
const user = await User.findOne({ email });
if (!user) {
console.log('no user'); //fjernes
return res.status(200).json({
errors: [{ msg: 'If user Exists, an email will be sendt' }],
});
}
const extToken = await Token.findOne({ userId: user._id });
if (extToken) {
await extToken.deleteOne();
}
const payload = {
user: {
id: user._id,
},
};
const secret = process.env.JWT_RESET_PASSWORD;
const webToken = jwt.sign(payload, secret, {
algorithm: 'HS256',
expiresIn: 3600,
});
const salt = await bcrypt.genSalt(10);
const tokenHash = await bcrypt.hash(webToken, salt);
const token = new Token({
userId: user._id,
token: tokenHash,
});
await token.save();
res
.status(200)
.header('Access-Control-Allow-Origin', 'http://localhost:60427')
// several ways is tried of the above
.json({ link: webToken, url: UrlLink });
return;
} catch (err) {
res.status(400).json({ errors: [{ msg: err }] });
return;
}
}
);
i have figured out that the cors error only appears if from either when I make a call to the database (not when connecting) og if I try to use crypt. If I don't make a cal to the database, or encrypt with bcryept, the cors error will not appear in my web browser.
PS: my frontend and backend is hosted separately, so the domain is not the same.
any help to figure this out will be much appreciated :)
I ran into this issue quite a bit I would make sure that you allow access at the very top of your server file so that its allowing access across all of your routes. Something like this
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use((_, res, next) => {
res.set('Access-Control-Allow-Origin', '*'); // or 'localhost:8888'
res.set('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS');
res.set(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
);
return next();
}); // sets headers before routes
// routes start here
app.use('/ip', ip);
app.use('/youtube', youtube);
Make sure that if you're setting the response headers you're doing so BEFORE all of your routes. Most of the times I've struggled with CORS is because I was only setting it on some routes some of the time. This setup will ensure every route is g2g.
You can mention the origins allowed as shown below
const cors = require('cors');
app.use(cors({
origin: ['http://localhost', 'https://localhost/']
}));
or for all origins
app.use(cors({
origin: '*'
}));
Solved!
Turnes out in this case, the error is misleading at best. I had forgotten to add the new environment variables (env. variables to connect to database, and to use JWT) to netlify for deployment. When that was done, it worked without changing any more code. PS: all code was changed according to the answers above.
Thank you to all the contributors :)
Why this resolved in a cors error in google chrome, I dont know. :)
I keep getting the "No 'Access-Control-Allow-Origin' header is present on the requested resource" error even though I have the following middleware in my express server (which is placed before all other middleware):
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const PORT = process.env.PORT || 5000;
const cors = require("cors");
const workoutRoutes = require("./routes/workoutRoutes");
const exerciseRoutes = require("./routes/exerciseRoutes");
const userRoutes = require("./routes/userRoutes");
const checkAuth = require("./middleware/check-auth");
app.use(function (req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, OPTIONS, PUT, PATCH, DELETE"
);
res.setHeader(
"Access-Control-Allow-Headers",
"X-Requested-With,content-type, Authorization"
);
res.setHeader("Access-Control-Allow-Credentials", true);
next();
});
app.use("/users", userRoutes);
app.use(checkAuth);
app.use("/workouts", workoutRoutes);
app.use("/exercises", exerciseRoutes);
app.listen(PORT);
I know this question has been asked multiple times, but none of the solutions have worked for me, including using the cors npm package.
This is the alternative middleware that I tried using the cors module, which produces the same error:
app.options("*", cors());
app.use(cors({ origin: null }));
Any advice into why I could still be getting this error would be greatly appreciated. Thank you.
I figured out the issue, I was making the requests without a valid token, causing the following checkAuth middleware to respond with 'No valid token'.
const jwt = require("jsonwebtoken");
module.exports = (req, res, next) => {
try {
const token = req.headers.authorization;
if (!token) {
res.send("No valid token");
}
next();
} catch (error) {
console.log(error);
return;
}
};
What I still don't understand is why this response did not have the appropriate headers attached if the checkAuth middleware is run after the cors middleware. Anyway, thank you all for your help.
I cannot fetch POST requests to my Express router. I have many GET requests which work fine, but this is my first POST request and it is not working.
My frontend code looks like this:
export async function postHamster(name, age) {
try {
await fetch('/hamsters/api/new-hamster',
{
method: 'POST',
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name: name,
age: age
})
})
console.log("postHamster has run") //LOGGED
}
catch (e) {
console.error(e)
}
}
The response will always be:
fetchData.js:38 POST http://localhost:3000/hamsters/api/new-hamster 404 (Not Found)
I have triple-checked the path and it cannot be in error. The backend path is "router.get('api/new-hamster', async (req, res)..." in the file 'hamsters.js'.
I have also put the backend function at the very top of its file, to ensure that it is not overrruled by any other function in the file.
This is my server.js:
// THIS FIRST FUNCTION I JUST COPIED FROM A SOLUTION BUT IT DOES NOT SEEM TO HELP
// routes/index.js
module.exports = (express) => {
// Create express Router
var router = express.Router();
// add routes
server.route('/hamsters/api/new-hamster')
.post((req, res) => {
res.setHeader('Content-Type', 'application/json');
res.send('You sent: sdadad to Express');
});
return router;
}
const express = require('express');
const server = express();
const serverPort = process.env.PORT || 1234;
server.use(express.static(__dirname + '/../build'))
let data = require('./data.json')
const { Router } = require('express');
let router = new Router();
//USE BODY-PARSER BEFORE REGISTERING ROUTES!
const bodyParser = require('body-parser')
server.use(bodyParser.urlencoded({ extended: true }));
server.use(bodyParser.json())
server.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
// ROUTES
const hamstersRoute = require('./routes/hamsters');
const chartsRoute = require('./routes/charts')
const gamesRoute = require('./routes/games')
const statsRoute = require('./routes/stats')
const imagesRoute = require('./routes/images')
const uploadRoute = require('./routes/upload')
server.use('/assets', express.static("assets"))
server.use(express.static('public'))
server.use('/hamsters', hamstersRoute)
server.use('/charts', chartsRoute)
server.use('/games', gamesRoute)
server.use('/stats', statsRoute)
server.use('/images', imagesRoute)
server.use('/upload', uploadRoute)
server.listen(serverPort, () => {
console.log(`Server is up n running on port ${serverPort}!`)
})
module.exports = data;
I have looked at these threads:
Cannot GET/POST with express Router()
Express.js routers post request returns 404
Express: router cannot read POST request
Have you checked the url you're trying to post to in the network tab in the console? I think you need to add a / before api in the backend route: router.get('/api/new-hamster', async (req, res)...".
You have this:
server.use(bodyParser.urlencoded({ extended: true }));
Instead of this:
server.use(bodyParser.urlencoded({ extended: false }));
I have used Postman to send Post requests and they are working fine but when I try to use axios it is giving me this error.
createAnimeList.js:27
Error: Network Error
at createError (createError.js:16)
at XMLHttpRequest.handleError (xhr.js:83)
xhr.js:178 POST http://localhost:4000/animes/add
net::ERR_CONNECTION_REFUSED
This is my backend code
router.post("/add", async (req, res) => {
console.log("Heeeere");
console.log(req.body.animeName);
var anime = new Animes({
animeName: req.body.animeName,
});
anime = await anime.save();
return res.send(anime);
});
Here is my React code where I am using Axios
onSubmit(event) {
event.preventDefault();
const anime = {
animeName: this.state.animeName,
};
console.log(anime);
axios
.post("http://localhost:4000/animes/add", anime)
.then((res) => console.log(res.data))
.catch((err) => console.log(err));
//window.location = "/anime";
}
Seems like a CORS issue
Install that on your node server:
https://www.npmjs.com/package/cors
Here is a simple example of node server with CORS enabled using this lib.
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
app.get('/products/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port
80')
})
you need to enable CORS( Cross-Origin-Resoruce-Sharing)
you can either use the cors package
https://www.npmjs.com/package/cors
or this code
place this controller before every controller in your application
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*'); // to enable calls from every domain
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST, PUT, PATCH, DELETE'); // allowed actiosn
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
if (req.method === 'OPTIONS') {
return res.sendStatus(200); // to deal with chrome sending an extra options request
}
next(); // call next middlewer in line
});
It's a CORS issue:
You need to add the follow code in your backend:
const cors = require('cors');
const express = require('express');
const app = express();
app.use(cors({
credentials:true,
origin: ['http://localhost:PORT']
}));
Inside origin array you need to insert those urls who are in the white list.
In summary I am using a viewer like api of dicom files called cornerstone, for this I connect to the WADO service of dc4chee to get the dicom, dcm4chee runs port 8080, and my application on node uses port 3000, so I am trying to show The browser's dicom.
https://www.npmjs.com/package/cornerstone-wado-image-loader
This is the error displayed by the browser
XMLHttpRequest can not load http: // localhost: 8080 / wado? RequestType = WADO & studyUID = 1.2.840.113704.1.111.5 ... 26513.429 & contentType = application% 2Fdicom & transferSyntax = 1.2.840.10008.1.2. In 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http: // localhost: 3000' is therefore not allowed access.
In the documentation specified
Note that the web server must support Cross source resource sharing or the image will fail to load. If you are unable to get CORS enabled on the web server you are loading DICOM P10 instances from, you can use a reverse proxy. Here's a simple Node.js based on http-proxy that adds CORS headers that you might find useful.
And show this example code but I'm using express and this code does not work
Var http = require ('http'),
HttpProxy = require ('http-proxy');
Var proxy = httpProxy.createProxyServer ({target: 'http: // localhost: 8042'}) .listen (8000);
Proxy.on ('proxyRes', function (proxyReq, req, res, options) {
// add the CORS header to the response
Res.setHeader ('Access-Control-Allow-Origin', '*');
});
Proxy.on ('error', function (e) {
// suppress errors
});
Also use npm cors here the code
Var express = require ('express')
Var cors = require ('cors')
Var app = express ()
App.get ('/ products /: id', cors (), function (req, res, next) {
Res.json ({msg: 'This is CORS-enabled for a Single Route'))
})
App.listen (80, function () {
Console.log ('CORS-enabled web server listening on port 80')
})
But with this I enable the cors on port 3000 and not the 8080, I need the mode to activate or add 'Access-Control-Allow-Origin in headers response and not in header request,
How can I do to add CORS on port 8080 where dcm4chee runs from NODEjs?
update!
The server responds with the following;
RESPONDE HEADER
Content-Type:application/dicom
Date:Sat, 01 Apr 2017 01:15:38 GMT
Expires:0
Server:Apache-Coyote/1.1
Transfer-Encoding:chunked
X-Powered-By:Servlet 2.4; JBoss-4.2.3.GA (build: SVNTag=JBoss_4_2_3_GA
date=200807181439)/JBossWeb-2.0
REQUEST HEADER
Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:es-ES,es;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Host:localhost:8080
Origin:http: //localhost:3000
Referer:http: //localhost:3000/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like
Gecko) Chrome/55.0.2883.87 Safari/537.36
HOW TO ENABLE THE CORS IN RESPONSE HEADER??
do
npm install cors --save
and just add these lines in your main file where your request is going.
const cors = require('cors');
const express = require('express');
const app = express();
app.use(cors());
Adding CORS(Cross-Origin-Resource-Sharing) to your node, express app is quite easy...
You need to install cors library via npm first, using the command below:
npm install cors -S
and if you need it globally, just add -g flag to it...
Then in your express app, do this:
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
Also these are other examples for cors from their doc:
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
app.get('/products/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
Configuring CORS Asynchronously:
var express = require('express')
var cors = require('cors')
var app = express()
var whitelist = ['http://example1.com', 'http://example2.com']
var corsOptionsDelegate = function (req, callback) {
var corsOptions;
if (whitelist.indexOf(req.header('Origin')) !== -1) {
corsOptions = { origin: true } // reflect (enable) the requested origin in the CORS response
}else{
corsOptions = { origin: false } // disable CORS for this request
}
callback(null, corsOptions) // callback expects two parameters: error and options
}
app.get('/products/:id', cors(corsOptionsDelegate), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for a whitelisted domain.'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
To enable cors you can do this:
var cors = require('cors');
app.use(cors());
// to change your ports for different cors stuff:
app.set('port', process.env.PORT || 3000);
app.listen(app.get('port'), function() {
console.log('we are listening on: ',
app.get('port'))
});
Remember that cors are middleware, so you will want to have app.use before it so that your incoming requests will go through cors before they hit your routes.
You can change the ports depending on which one you want to use. I am pretty sure you can also replace the || with && to listen on multiple ports and set cors on those.
In raw node, I believe you have to use the writeHead, but I am not sure about the raw node implementation.
The error displayed by the browser means, server localhost:8080 refused a request from localhost:3000, It seems cors didn't set well on server localhost:8080.
The response header should have something like this:
Access-Control-Allow-Headers:Content-Type,Content-Length, Authorization, Accept,X-Requested-With
Access-Control-Allow-Methods:PUT,POST,GET,DELETE,OPTIONS
Access-Control-Allow-Origin:*
Try add cors header in your 8080 server.
app.all('*', function (req, res) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
//...
});
CORS didn't work on localhost until I added http:// to request url
Not working localhost:3001
Working fine http://localhost:3001
This is what my working code looks at the end
Node side
var cors = require('cors')
const app = express();
app.use(cors()); // Make sure this line comes right after express()
Front-end side
let response = await axios.post("http://localhost:3001/uploadFile", formData);
// the http:// is required cors to work for localhost
This code is helped me to resolve the resources cors issue with the express. And You can use other options easily with the asynchronous origin configuration.
var cors = require('cors'); //import cors module
var whitelist = ['http://localhost:8000', 'http://localhost:8080']; //white list consumers
var corsOptions = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true);
} else {
callback(null, false);
}
},
methods: ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS'],
optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
credentials: true, //Credentials are cookies, authorization headers or TLS client certificates.
allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'device-remember-token', 'Access-Control-Allow-Origin', 'Origin', 'Accept']
};
app.use(cors(corsOptions)); //adding cors middleware to the express with above configurations
To solve this problem first of all you have to understand what Access-Control-Allow-Origin: The value for this Header will be the host from where you will send a request to your server ( eg express ).
Step 1: allow cors on the server side, (to allow cross origin request you can use * instead of http://localhost:3000:
var express = require("express");
var app = express();
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*"); // update to match the domain you will make the request from
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
Step 2: just use your http client , I am using Axios:
var qs = require("querystring");
var axios = require("axios");
const sendEmail = (email, subject, template) => {
var data = qs.stringify({
email: email,
subject: subject,
template: template,
});
var config = {
method: "post",
url: "https://abc-domain.com/endpoint",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
data: data,
};
axios(config)
.then(function(response) {
console.log(JSON.stringify(response.data));
})
.catch(function(error) {
console.log(error);
});
};
module.exports = sendEmail;
//Définition des CORS Middleware
app.use(function(req, res, next) {
res.setHeader("Access-Control-Allow-Headers", "X-Requested-With,content-type, Accept,Authorization,Origin");
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, PATCH, DELETE");
res.setHeader("Access-Control-Allow-Credentials", true);
next();
});`enter code here`
I also met this issue.
To solve it I used CORS module and imported it into my routings:
import cors from 'cors';
const router = new Router();
router.get('/posts', cors(), PostController.getAll);
add the following in your route handler
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
for example instead of this
app.get("/monsters", (req, res) => {
const arr = [
{
name: "Abanoub",
id: "215",
},
{
name: "Mena",
id: "sd5",
}
];
res.send(arr);
});
use headers I mentioned before.
so the route handler will be like that:
app.get("/monsters", (req, res) => {
const arr = [
{
name: "Abanoub",
id: "215",
},
{
name: "Mena",
id: "sd5",
}
];
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.send(arr);
});