I have a REST api created with the restify module and I want to allow cross-origin resource sharing. What is the best way to do it?
You have to set the server up to set cross origin headers. Not sure if there is a built in use function or not, so I wrote my own.
server.use(
function crossOrigin(req,res,next){
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
return next();
}
);
I found this from this tutorial. http://backbonetutorials.com/nodejs-restify-mongodb-mongoose/
The latest version of Restify provides a plugin to handle CORS.
So you can now use it like this:
server.use(restify.CORS({
// Defaults to ['*'].
origins: ['https://foo.com', 'http://bar.com', 'http://baz.com:8081'],
// Defaults to false.
credentials: true,
// Sets expose-headers.
headers: ['x-foo']
}));
This works for me:
var restify = require('restify');
var server = restify.createServer();
server.use(restify.CORS());
server.opts(/.*/, function (req,res,next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", req.header("Access-Control-Request-Method"));
res.header("Access-Control-Allow-Headers", req.header("Access-Control-Request-Headers"));
res.send(200);
return next();
});
server.get('/test', function (req,res,next) {
res.send({
status: "ok"
});
return next();
});
server.listen(3000, function () {
console.log('%s listening at %s', server.name, server.url);
});
This is what worked for me:
function unknownMethodHandler(req, res) {
if (req.method.toLowerCase() === 'options') {
console.log('received an options method request');
var allowHeaders = ['Accept', 'Accept-Version', 'Content-Type', 'Api-Version', 'Origin', 'X-Requested-With']; // added Origin & X-Requested-With
if (res.methods.indexOf('OPTIONS') === -1) res.methods.push('OPTIONS');
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Headers', allowHeaders.join(', '));
res.header('Access-Control-Allow-Methods', res.methods.join(', '));
res.header('Access-Control-Allow-Origin', req.headers.origin);
return res.send(204);
}
else
return res.send(new restify.MethodNotAllowedError());
}
server.on('MethodNotAllowed', unknownMethodHandler);
I this code was taken from https://github.com/mcavage/node-restify/issues/284
CORS Plugin is deprecated in favor of https://github.com/Tabcorp/restify-cors-middleware. (Source: https://github.com/restify/node-restify/issues/1091.)
Below is a sample code regarding how to use
const corsMiddleware = require('restify-cors-middleware')
const cors = corsMiddleware({
preflightMaxAge: 5, //Optional
origins: ['http://api.myapp.com', 'http://web.myapp.com'],
allowHeaders: ['API-Token'],
exposeHeaders: ['API-Token-Expiry']
})
server.pre(cors.preflight)
server.use(cors.actual)
If anyone comes across this as of Feb 2018 there seems to be a bug that's been introduced, I couldn't get the restify-cors-middleware to work.
I'm using this work around for now:
server.pre((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
next();
});
To enable CORS for basic authentication I did the following. It did not work until the .pre methods were used instead of the .use methods
server.pre(restify.CORS({
origins: ['https://www.allowedip.com'], // defaults to ['*']
credentials: true,
headers: ['X-Requested-With', 'Authorization']
}));
server.pre(restify.fullResponse());
function unknownMethodHandler(req, res) {
if (req.method.toLowerCase() === 'options') {
var allowHeaders = ['Accept', 'Accept-Version', 'Content-Type', 'Api-Version', 'Origin', 'X-Requested-With', 'Authorization']; // added Origin & X-Requested-With & **Authorization**
if (res.methods.indexOf('OPTIONS') === -1) res.methods.push('OPTIONS');
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Headers', allowHeaders.join(', '));
res.header('Access-Control-Allow-Methods', res.methods.join(', '));
res.header('Access-Control-Allow-Origin', req.headers.origin);
return res.send(200);
} else {
return res.send(new restify.MethodNotAllowedError());
}
}
server.on('MethodNotAllowed', unknownMethodHandler);
I do it like this on my restify base app:
//setup cors
restify.CORS.ALLOW_HEADERS.push('accept');
restify.CORS.ALLOW_HEADERS.push('sid');
restify.CORS.ALLOW_HEADERS.push('lang');
restify.CORS.ALLOW_HEADERS.push('origin');
restify.CORS.ALLOW_HEADERS.push('withcredentials');
restify.CORS.ALLOW_HEADERS.push('x-requested-with');
server.use(restify.CORS());
you need to use restify.CORS.ALLOW_HEADERS.push method to push the header u want into restify first, then using the CORS middleware to boot the CORS function.
MOST OF THE PREVIOUS ANSWERS ARE FROM 2013 AND USE DEPRECATED EXAMPLES!
The solution (in 2017 at least) is as follows:
npm install restify-cors-middleware
Then in your server javascript file:
var corsMiddleware = require('restify-cors-middleware');
var cors = corsMiddleware({
preflightMaxAge: 5,
origins: ['*']
});
var server = restify.createServer();
server.pre(cors.preflight);
server.use(cors.actual);
And add whatever additional other options work for you. My use case was creating a localhost proxy to get around browser CORS issues during devolopment. FYI I am using restify as my server, but then my POST from the server (and to the server) is with Axios. My preference there.
npm listing for restify-cors-middleware
This sufficed in my case:
var server = restify.createServer();
server.use(restify.fullResponse());
server.get('/foo', respond(req, res, next) {
res.send('bar');
next();
});
It wasn't necessary to server.use(restify.CORS());
Also, it appears server.use() calls must precede server.get() calls in order to work.
This worked for me with restify 7
server.pre((req, res, next) => {
res.header('Access-Control-Allow-Origin', req.header('origin'));
res.header('Access-Control-Allow-Headers', req.header('Access-Control-Request-Headers'));
res.header('Access-Control-Allow-Credentials', 'true');
// other headers go here..
if(req.method === 'OPTIONS') // if is preflight(OPTIONS) then response status 204(NO CONTENT)
return res.send(204);
next();
});
I am using Restify 7.2.3 version and this code worked for me very well.
You need to install the restify-cors-middleware plugin.
const corsMiddleware = require('restify-cors-middleware')
const cors = corsMiddleware({
preflightMaxAge: 5, //Optional
origins: ['http://ronnie.botsnbytes.com', 'http://web.myapp.com'],
allowHeaders: ['API-Token'],
exposeHeaders: ['API-Token-Expiry']
})
server.pre(cors.preflight)
server.use(cors.actual)
const cors = require('cors');
const server = restify.createServer();
server.use(cors());
This worked for me
const restify = require('restify');
const corsMiddleware = require('restify-cors-middleware');
const cors = corsMiddleware({
origins: ['*']
});
const server = restify.createServer();
server.pre(cors.preflight);
server.use(cors.actual);
server.get('/api/products', (request, response) => {
response.json({ message: 'hello REST API' });
});
server.listen(3000, () => console.info(`port 3000`));
... is one brute-force solution, though you should be very careful doing that.
Related
we are trying me and my friend to deploy a project that's locally fully working.
But now we deployed it (the front to firebase the back to heroku),
and now every request we got cors policy
app.use(cors());
var allowCrossDomain = 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"
);
// intercept OPTIONS method
if ("OPTIONS" == req.method) {
res.send(200);
} else {
next();
}
};
app.use(allowCrossDomain);
app.use(bodyParser.json());
app.use("/function", couponRoutes);
mongoose
.connect( `mongodb+srv://${process.env.DB_USER}:${process.env.DB_PASSWORD}#cluster0.qvs4c.mongodb.net/${process.env.DB_NAME}?retryWrites=true&w=majority`
)
.then(() => {
app.listen(5000);
})
.catch((err) => {
console.log(err);
});
Thats the code for the back (I tried also without the allowcross domain) and nothing is working.
we are doing from the front regular axios request and its not working , hope for help.
You have to configure cors by passing a javascript object to configure it like the following
const corsOptions = {
"origin": "*",
"methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
"preflightContinue": false,
"optionsSuccessStatus": 200
"exposedHeaders": ['Content-Length', 'X-Requested-With', ' Authorization','Content-Type'],
}
app.use(cors(corsOptions))
You should use this instead of your code to get cors working
if you have multiple origins use the following snippet
var allowedOrigins = ['http://localhost:3000',
'http://yourapp.com'];
app.use(cors({
origin: function(origin, callback){
// allow requests with no origin
// (like mobile apps or curl requests)
if(!origin) return callback(null, true);
if(allowedOrigins.indexOf(origin) === -1){
var msg = 'The CORS policy for this site does not ' +
'allow access from the specified Origin.';
return callback(new Error(msg), false);
}
return callback(null, true);
}
}));
I have a Digital Ocean Linux server.
I deployed my REST API and also front end in the same server.
My Back End runs using Node.JS and front end using AngularJS.
After enabling HTTPS, I changed all the REST URLs into HTTPS.
Like this :
var mainHost = "https://xxx.xxx.xxx.xx:7000/api";
Now I'm getting this CORS error :
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://xxx.xxx.xxx.xx:7000/api/user_manage/login. (Reason: CORS request did not succeed).
I am using Node.JS CORS plugin also.
var cors = require('cors');
var app = express();
app.use(cors());
This started when I added HTTPS and I tried many things. Including changing the .htaccess and adding some meta tags. Still no good. What is the reason for this ? Why CORS error comes after adding HTTPS ? Please help me to solve this.
This is the controller call for the service layer :
sessionService.getAllSessions(100, 0).then(function (data) {
console.log(data);
$scope.allSessions = data.data;
});
And this is the service layer :
getAllSessions: function (limit, offset) {
return $http({
method: "GET",
url: host.session_manage + '/session/' + limit + '/' + offset
}).then(function (response) {
return response.data;
});
}
I'm not using headers in the service call as you can see in the above section.
This is the server code snippet :
var express = require("express");
var bodyParser = require("body-parser");
var morgan = require("morgan");
var config = require("./config");
// var cors = require('cors');
var app = express();
// app.use(cors());
// app.use(cors({
// origin: 'https://xxxxxx.com'
// }));
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.set('views', './app/views');
app.set('view engine', 'pug');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(morgan('dev'));
var session = require('./app/routes/session')(app, express);
app.use('/api/session_manage', session);
app.listen(config.port, function (err) {
if (err) {
console.log(err);
} else {
console.log("localhost:7000");
}
});
Thank you guys.
You are in production you don't want to allow CORS access for all origins but if you need to allow cross origin requests from some specified host(s) you can do add the following code:
server.use(cors({
origin: 'https://example.com'
}));
This will allow https://example.com to send cross origin requests to your Express server without the Same Origin Policy getting in the way.
You can also enable CORS for a single Express route
server.get('/endpoint', cors(), function (req, res, next) {
res.json({msg: 'This has CORS-enabled for only this route: /endpoint'})
})
If you want to allow multiple origins you need to use a function (for origin instead of a string) that dynamically set the CORS header depending on the origin making the request and a white list that you specify which contains the origin to allow.
var whitelist = ['http://example.com', 'http://othersite.com'];
var options = { origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
server.use(cors(options))
I have two servers in the nodejs app.
I am using two servers http-server for static html file (i.e. index.html) and express for node APIs. Now I am getting the CORS filter error. even if I have enabled the cors filter on both the servers.
I have tried these combinations.
1. Enabling it on Node server using middleware.
i.e following code.
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");
res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
next();
});
and on http-server using following command.
http-server --cors
I am still getting following error.
I am guessing here that enabling on both server won't work as both resources will have different CORS values. But how can I solve it? Any help would be appreciated.
Looking at the networks tab in the developer tools I can see following for the API request.
Update-1 tried cors package
I have tried following code samples with each time a server restart.
app.use(cors());
and this one too.
app.use(cors());
app.options('*', cors());
and this one with specific configuration.
app.use(cors());
var whitelist = ['http://localhost:8080']
var corsOptions = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
app.options('*', cors(corsOptions));
Everytime I am getting the same response in output console.
These are the routes.
module.exports = function(app){
app.get('/get_tuna/:id', function(req, res){
tuna.get_tuna(req, res);
});
app.get('/add_tuna/:tuna', function(req, res){
tuna.add_tuna(req, res);
});
app.get('/get_all_tuna', function(req, res){
console.log('###### ++++++++++ 2 - This is called first');
tuna.get_all_tuna(req, res);
});
app.get('/change_holder/:holder', function(req, res){
tuna.change_holder(req, res);
});
app.get('/api/get_available_vault_balance/', function(req, res){
/// --------- 3
console.log('VAULT >> API is called >>> :) ');
vaultbackendservice.get_available_vault_balance(req, res);
});
}
I've seen several questions and answers around this and mine is half working.
I have a node.js api server with url api.domain.com and the website on an nginx server at www.domain.com when I do the following in angular the request goes through on the api server, I see the request I see it getting parsed and put into the database. However, on the client side I do not get a return right away and then eventually I will see No 'Access-Control-Allow-Origin' header is present on the requested resource.
I know what is causing this behavior but shouldn't it throw the error before it hits the API server? Also note that the node.js server has cors enabled. The response that should be coming back is json.
$http({
method: 'POST',
url: "http://api.domain.com/addtrans/" + $scope.accountID,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, PUT',
'Content-Type': 'application/x-www-form-urlencoded'
},
transformRequest: function (obj) {
var str = [];
for (var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: {
payload: JSON.stringify(trans)
}
}).success(function (result) {
$scope.trans = {};
console.log(result);
});
I have used the below middleware for all of our projects and it has been proven to work best.
const allowCors = (req, res, next) => {
/** Allow all origins, for now TODO */
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Headers', 'Authorization, Content-Type');
res.header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE');
/** Browser check for pre-flight request to determine whether the server is webdav compatible */
if ('OPTIONS' == req.method) {
res.sendStatus(204);
}
else next();
};
// Put this code before the routes you want to allow CORS to
app.use(allowCors);
You should change the Allow-Origin to something more restricted for security reasons.
The above code covers CORS as well as pre-flight on most browsers(this ia major issue we were having in the beginning).
i used this a while ago (express 3.x):
// npm install --save cors
var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());
app.use(express.static());
app.get('*', function(){});
require('http').createServer(app).listen(3000)
Remember that the cors header should be on the response which is coming from server not the request which is sent from client.
You can use a middleware to enable cors on the server:
//CORS middleware
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', 'example.com');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
//...
app.configure(function() {
...
app.use(allowCrossDomain);
...
});
I have the following code in Angular.JS
$scope.resolve = function(){
alert('In here');
$http.get('http://cdsws.u-strasbg.fr/axis/services/Sesame?method=sesame&resultType=x&name=m3')
.success(function(data,status,headers,config){
alert("data"+data);
})
.error(function(data,status,headers,config){
alert("Error in Web service!"+status);
});
};
I have added the required headers in express but still not able to call the web service
var app = express();
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin','*');
res.header('Access-Control-Allow-Credentials', 'true');
res.header('Access-Control-Allow-Methods', 'GET,HEAD,PUT,PATCH,POST,DELETE');
res.header('Access-Control-Expose-Headers', 'Content-Length');
res.header('Access-Control-Allow-Headers', 'Accept, Authorization, Content-Type, X-Requested-With, Range');
if (req.method === 'OPTIONS') {
return res.send(200);
} else {
return next();
}
});
What else needs to be done to enable CORS?
I even tried using the cors middleware in node Jsbut no success!
var cors= require('cors');
var corsOptions = {
origin: 'http://localhost:3001/'
};
app.use(cors(corsOptions));
is there any way by which we can access the other domain URL , I can not add Access-Control-Allow-Headers to the other domain, the change needs to be done on the client side.