This question already has answers here:
How does the 'Access-Control-Allow-Origin' header work?
(19 answers)
Closed 2 years ago.
When I create two servers using Nodejs with http and both have express as request handler, one is running at localhost:3000, which is used for handling api. And the other at localhost:5000 and I try to fetch the api from localhost:3000, I expect to get a cors error, but surprisingly I can fetch it with no error. I wonder why, is it because of express?
The localhost:5000 code
const express = require('express');
const app = express();
const axios = require('axios');
const http = require('http');
const server = http.createServer(app);
app.get('/', async (req, res) => {
try {
const response = await axios.get('http://localhost:3000/users');
console.log(typeof response.data);
res.send(response.data[1]);
} catch(err) {
console.error(err);
}
});
server.listen(5000);
try putting cors rules,
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
res.setHeader('Access-Control-Allow-Methods', 'GET,HEAD,PUT,PATCH,POST,DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
Related
This question already has answers here:
socket.io, 'Access-Control-Allow-Origin' error
(9 answers)
Closed 1 year ago.
I am getting following error:
Access to XMLHttpRequest at 'http://localhost:8001/socket.io/?EIO=3&transport=polling&t=NWrnTy1' from origin 'http://localhost' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
my node server code:
//import express from "express";
//import http from "http";
const app = require("express")();
const server = require("http").createServer(app);
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
const io = require("socket.io")(server);
io.on("connection", () => {
console.log("Connected!");
});
var redis = require('redis');
var url = "redis://localhost:6379"
var client = redis.createClient(url);
client.on('message', function(channel, msg) {
io.sockets.emit(msg);
});
client.subscribe('JoinCall');
server.listen(8001);
my index.html on apache:
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script>
//var socket = io();
var socket = io.connect('http://localhost:8001');
sock.on('twits', function(msg) {
console.log('message received: '+msg);//Do something with message here.
});
</script>
I had ton of problems with CORS and they were all resolved by installing the npm package cors and let it do this job. I would suggest to remove your manual setting headers and try this instead. Saved my life.
Install the cors package by running 'npm i cors'. Then in your server file add these:
const cors = require('cors');
// Add these lines above any route / mounting
app.use(cors());
app.options('*', cors());
in socket.io client I used a neutral transport layer:
var socket = io('http://localhost:8001', { transports : ['websocket'] });
I created a REST Api using nodejs and mongodb and i wanted to test it in postman but while doing so I am getting a CORS error.
var express = require('express');
var log = require('morgan')('dev');
var bodyParser = require('body-parser');
var properties = require('./config/properties');
var db = require('./config/database.js');
//hero routes
var herosRoutes = require('./api/heros/heros.routes');
var app = express();
//configure bodyparser
var bodyParserJSON = bodyParser.json();
var bodyParserURLEncoded = bodyParser.urlencoded({extended:true});
//initialise express router
var router = express.Router();
// call the database connectivity function
db.mongoc();
// configure app.use()
app.use(log);
app.use(bodyParserJSON);
app.use(bodyParserURLEncoded);
// Error handling
app.use(function(req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Credentials", "true");
res.setHeader("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
res.setHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Origin,Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers,Authorization");
next();
});
// use express router
app.use('/api',router);
//call heros routing
herosRoutes.hero(router);
// intialise server
app.listen(properties.PORT, (req, res) => {
console.log(`Server is running on ${properties.PORT} port.`);
})
Whenever i make any create or get request, i get this CORS error in postman. How to solve this?
CORS Error: The request has been blocked because of the CORS policy
Have you tried the CORS package from Express? It's a simple setup:
npm i cors
Then just use it in your app (this enables ALL CORS requests):
app.use(cors());
Docs
Also answered here.
if someone is still having this issue, Postman doesn't provide an origin when calling the API, so when we have restricted CORS policy an error is generated saying Error: Not allowed by CORS.
Sample code for bypassing this issue is this:
const whitelist = ['https://localhost:3001']
const corsOptions = {
origin: function (origin, callback) {
if(!origin){//for bypassing postman req with no origin
return callback(null, true);
}
if (whitelist.indexOf(origin) !== -1) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
app.use(cors(corsOptions));
I implemented a basic express app for cloud functions. I have used the cors library to enable cors. There are 4 api endpoints and all 4 need to be preflighted. For some reason, access-control-allow-origin:* header is placed on the 3 routes and not the 4th one.
Precisely, i'm using Content-Type: application/json for POST requests, which need to be preflighted. All the endpoints need the same headers, but it isn't applied for the last one.
Code snippets:
const express = require("express");
const cors = require("cors");
const bodyParser = require('body-parser');
const admin = require("firebase-admin");
admin.initializeApp();
const app = express();
app.use(cors());
app.use(bodyParser.json());
app.use(express.json());
app.use('/', require('./controllers'));
exports.apiv2 = functions.https.onRequest(app);
Routes:
const express = require('express');
const router = express.Router();
router.use('/create-player', require('./createPlayer'));
router.use('/create-game', require('./createGame'));
router.use('/join-game', require('./joinGame'));
router.use('/move', require('./makeMove'));
// 404 error handler for invalid player and game IDs
router.use((err, req, res, next) => {
res.json({ error: err.msg });
});
module.exports = router;
For the /move route alone, the cors request fails, even after preflight request passes. Preflight passes with 204. The actual request fails for some reason. The POST request fails
Is there any particular access control header is not placed by express for one endpoint alone ?
You can set this middleware before your routes middleware in app.js to solve thi problem:
// app.js
...
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
if ('OPTIONS' === req.method)
res.sendStatus(200);
else
next();
});
...
app.use(routes);
Then, this will be applied for all of your routes.
This is my simple nodejs app using express:
const express = require('express');
const app = express();
const user = require('./routes/user').user;
const browser = require('./routes/browser');
const bodyParser = require('body-parser');
// CORS middleware
const allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', '*');
res.header('Access-Control-Allow-Headers', '*');
next();
}
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(allowCrossDomain);
app.use('/', user);
app.use('/', browser);
const port = process.env.PORT || 4001;
app.listen(port, function() {
console.log('Express server listening on port ' + port)
});
Route handler "browser", where I added middleware:
const express = require('express');
const router = express.Router();
router.use(function (req, res, next) {
console.log(req.body);
next();
});
router.post('/get-content', (req, res) => {
});
Console
Here I got strange behaviour with middleware. I want to get request body data, but in console I see empty object instead expected body with content. After calling next() middleware fires second time and finally I am getting request body. Help me understand middleware behaviour in my case.
It`s can be help. Install cors package, and give it in express.use.
https://www.npmjs.com/package/cors
Middleware to support CORS pre-flight requests
const allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', '*');
res.header('Access-Control-Allow-Headers', '*');
//intercepts OPTIONS method
if ('OPTIONS' === req.method) {
res.sendStatus(200);
} else {
next();
}
}
The code below does not work
app.post('/blah', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, HEAD');
res.status(204).send();
});
Note that I don't want turn on CORS for the whole app.
you can use something like this :
var express = require('express')
var cors = require('cors')
var corsOptions = { origin: 'http://yourapp.com'}
var app = express()
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for a Single Route'})
})
app.listen(8080, function () {
console.log('CORS-enabled web server listening on port 8080')
})
By default, only 6 response headers are exposed over CORS:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
If you want to expose other headers, you can use the exposedHeaders option:
corsOptions = {
exposedHeaders: ['Content-Length', 'X-Foo', 'X-Bar'],
}
Please refer this for more detail on CORS:
More detail on cors
Posting this as an answer since it turned out to be the issue (per my earlier comment). Depending upon the exact CORS request you are making, then browser may decide that it needs to do a pre-flight of the request. If it does, then you also need to set the custom headers in a matching OPTIONS request.
A number of things can trigger a pre-flight such as custom headers, certain verbs being used, certain auth mechanisms, etc...
There's a description of what types of requests trigger a pre-flight here in these articles:
Using CORS
Cross Origin Resource Sharing
Basically, it's any request that isn't defined as a "simple request" where simple requests only use GET, HEAD and POST and only a small set of custom headers. Anything else and even some values for certain headers will trigger a preflight request where the browser sends an OPTIONS request to the same URL request pre-flight authorization before sending the actual URL.
What version of Express are you using? v4 of the API exposes a set() method on res where you can define headers. If passing multiple headers, you pass an object. Try something like this:
res.set({
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, PUT, POST, DELETE, HEAD'
});
Documentation.
Building on Clark Jung's reply, you can use https://github.com/expressjs/cors#enable-cors-for-a-single-route
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')
})
Why don't you use https://github.com/expressjs/cors. You can just use like this.
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')
})
Or refer to here https://enable-cors.org/server_expressjs.html
app.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();
});
app.get('/', function(req, res, next) {
// Handle the get for this route
});
app.post('/', function(req, res, next) {
// Handle the post for this route
});