Expressjs How to enable CORS on just one route? - node.js

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
});

Related

CORS header not applied for a particular route in Express cloud functions

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.

CORS error not showing when using express [duplicate]

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();
});

How to manage CORS policy properly in express?

I am trying to allow access from everywhere.
I have tried using app middleware:
app.use(function (req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader('Access-Control-Allow-Methods', '*');
res.setHeader("Access-Control-Allow-Headers", "*");
next();
});
I have tried using it in the route:
app.post('/login',function(req,res){
var login = req.body;
var sess = req.session;
if (!login.email && !login.pwd){
return res.status(401);
}
res.header("Access-Control-Allow-Origin", '*');
res.header("Access-Control-Allow-Headers", '*');
.... more code here
Both do not work. I keep getting an error: "Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource."
Further down the server, we use similar code for another route, which works:
app.post('/questar',function(req,res){
//allow xhr post from retireup domains
var cors = {
origin: "https://www.website.com";
};
res.header("Access-Control-Allow-Origin", cors.origin);
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.type('application/json');
I cannot tell the difference between the code, but only one set works. Any ideas why? This seems like an issue that shouldn't be so complicated. Thanks
After applying "cors" middleware. You should be passed "http://" before "localhost:". in url send to by Axios like this:
axios.get("http://localhost:8080/api/getData")
.then(function (response) {
this.items= response.data;
}).catch(function (error) {
console.log(error)
});
MDN has a very short explanation on how a server should respond to a Preflight Request.
You handle CORS preflight requests by handling the HTTP OPTIONS method (just like you would handle GET and POST methods) before handling other request methods on the same route:
app.options('/login', ...);
app.get('/login'. ...);
app.post('/login'. ...);
In your case, it might be as simple as changing your app.use() call to app.options(), passing the route as the first argument, setting the appropriate headers, then ending the response:
app.options('/login', function (req, res) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader('Access-Control-Allow-Methods', '*');
res.setHeader("Access-Control-Allow-Headers", "*");
res.end();
});
app.post('/login', function (req, res) {
...
});
Configure the CORS stuff before your routes, not inside them.
Here, like this (from enable-cors.org):
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
});
I always configure it like this in my Express+Angular apps and it works just fine.
Hope it helps.
First install, the "cors" package from npm: npm i -S cors
Then enable it in your express server.
var express = require('express'),
cors = require('cors');
const app = express();
app.use(cors());
...
Following some standard node projects out there, below CORS configuration worked for me always. It requires the npm package 'cors'. Note: Origin * means enabling responses to any origin and replies with status code 200. If this needs to be limited to one domain, update the origin accordingly. Ex: [origin: 'http://exampleui.com']
var cors = require('cors');
var corsOptions = {
origin: '*',
optionsSuccessStatus: 200,
}
app.use(cors(corsOptions));
app.use(express.json())
Following other's answers, this worked for me:
res.setHeader("Access-Control-Allow-Origin", 'http://myDomain:8080');
res.setHeader('Access-Control-Allow-Methods', 'POST,GET,OPTIONS,PUT,DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Accept');
All you have to whitelist the domains name to avoid getting cors error messages.
There is a plugin called cors, installed it into your project using this command
npm i cors
after installing use this code to remove the cors related errors form your project.
const cors = require('cors');
const corsOption = {
credentials: true,
origin: ['http://localhost:3000', 'http://localhost:80']
}
app.use(cors(corsOption));
In the origin section you can pass any domain to whitelist it. If you want to whitelist all the domain names, instead of passing the the urls array. you can pass '*' over there.
Example : origin: '*'
credentials: Configures the Access-Control-Allow-Credentials CORS header. Set to true to pass the header, otherwise it is omitted.

What is the proper syntax to allow red api access from any origin in my node express application [duplicate]

I am trying to support CORS in my Node.js application that uses the Express.js web framework. I have read a Google group discussion about how to handle this, and read a few articles about how CORS works. First, I did this (code is written in CoffeeScript syntax):
app.options "*", (req, res) ->
res.header 'Access-Control-Allow-Origin', '*'
res.header 'Access-Control-Allow-Credentials', true
# try: 'POST, GET, PUT, DELETE, OPTIONS'
res.header 'Access-Control-Allow-Methods', 'GET, OPTIONS'
# try: 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept'
res.header 'Access-Control-Allow-Headers', 'Content-Type'
# ...
It doesn't seem to work. It seems like my browser (Chrome) is not sending the initial OPTIONS request. When I just updated the block for the resource I need to submit a cross-origin GET request to:
app.get "/somethingelse", (req, res) ->
# ...
res.header 'Access-Control-Allow-Origin', '*'
res.header 'Access-Control-Allow-Credentials', true
res.header 'Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS'
res.header 'Access-Control-Allow-Headers', 'Content-Type'
# ...
It works (in Chrome). This also works in Safari.
I have read that...
In a browser implementing CORS, each cross-origin GET or POST request is preceded by an OPTIONS request that checks whether the GET or POST is OK.
So my main question is, how come this doesn't seem to happen in my case? Why isn't my app.options block called? Why do I need to set the headers in my main app.get block?
I found the easiest way is to use the node.js package cors. The simplest usage is:
var cors = require('cors')
var app = express()
app.use(cors())
There are, of course many ways to configure the behaviour to your needs; the page linked above shows a number of examples.
Try passing control to the next matching route. If Express is matching app.get route first, then it won't continue onto the options route unless you do this (note use of next):
app.get('somethingelse', (req, res, next) => {
//..set headers etc.
next();
});
In terms of organising the CORS stuff, I put it in a middleware which is working well for me:
// CORS middleware
const allowCrossDomain = (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(() => {
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: `cool beans` }));
app.use(express.methodOverride());
// CORS middleware
app.use(allowCrossDomain);
app.use(app.router);
app.use(express.static(`public`));
});
To answer your main question, the CORS spec only requires the OPTIONS call to precede the POST or GET if the POST or GET has any non-simple content or headers in it.
Content-Types that require a CORS pre-flight request (the OPTIONS call) are any Content-Type except the following:
application/x-www-form-urlencoded
multipart/form-data
text/plain
Any other Content-Types apart from those listed above will trigger a pre-flight request.
As for Headers, any Request Headers apart from the following will trigger a pre-flight request:
Accept
Accept-Language
Content-Language
Content-Type
DPR
Save-Data
Viewport-Width
Width
Any other Request Headers will trigger the pre-flight request.
So, you could add a custom header such as: x-Trigger: CORS, and that should trigger the pre-flight request and hit the OPTIONS block.
See MDN Web API Reference - CORS Preflighted requests
To stay in the same idea of routing. I use this code :
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
Similar to http://enable-cors.org/server_expressjs.html example
do
npm install cors --save
and just add these lines in your main file where your request going (keep it before any route).
const cors = require('cors');
const express = require('express');
let app = express();
app.use(cors());
app.options('*', cors());
I have made a more complete middleware suitable for express or connect. It supports OPTIONS requests for preflight checking. Note that it will allow CORS access to anything, you might want to put in some checks if you want to limit access.
app.use(function(req, res, next) {
var oneof = false;
if(req.headers.origin) {
res.header('Access-Control-Allow-Origin', req.headers.origin);
oneof = true;
}
if(req.headers['access-control-request-method']) {
res.header('Access-Control-Allow-Methods', req.headers['access-control-request-method']);
oneof = true;
}
if(req.headers['access-control-request-headers']) {
res.header('Access-Control-Allow-Headers', req.headers['access-control-request-headers']);
oneof = true;
}
if(oneof) {
res.header('Access-Control-Max-Age', 60 * 60 * 24 * 365);
}
// intercept OPTIONS method
if (oneof && req.method == 'OPTIONS') {
res.send(200);
}
else {
next();
}
});
Do something like this:
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();
});
install cors module of expressjs. you can follow these steps >
Installation
npm install cors
Simple Usage (Enable All CORS Requests)
var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());
for more details go to https://github.com/expressjs/cors
Testing done with express + node + ionic running in differente ports.
Localhost:8100
Localhost:5000
// CORS (Cross-Origin Resource Sharing) headers to support Cross-site HTTP requests
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
});
first simply install cors in your project.
Take terminal(command prompt) and cd to your project directory and run the below command:
npm install cors --save
Then take the server.js file and change the code to add the following in it:
var cors = require('cors');
var app = express();
app.use(cors());
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'DELETE, PUT, GET, POST');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
This worked for me..
Some time ago, I faced this problem so I did this to allow CORS in my nodejs app:
First you need to install cors by using below command :
npm install cors --save
Now add the following code to your app starting file like ( app.js or server.js)
var express = require('express');
var app = express();
var cors = require('cors');
var bodyParser = require('body-parser');
//enables cors
app.use(cors({
'allowedHeaders': ['sessionId', 'Content-Type'],
'exposedHeaders': ['sessionId'],
'origin': '*',
'methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
'preflightContinue': false
}));
require('./router/index')(app);
This works for me, as its an easy implementation inside the routes, im using meanjs and its working fine, safari, chrome, etc.
app.route('/footer-contact-form').post(emailer.sendFooterMail).options(function(req,res,next){
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
return res.send(200);
});
If you want to make it controller specific, you can use:
res.setHeader("X-Frame-Options", "ALLOWALL");
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST, GET");
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
Please note that this will also allow iframes.
In my index.js I added:
app.use((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, PUT, DELETE, OPTIONS");
next();
})
cors package is recommended way to for solving the CORS policy issue in express.js, but you also need to make sure to enable it for app.options as well, like below:
const cors = require('cors');
// enable cors
app.use(
cors({
origin: true,
optionsSuccessStatus: 200,
credentials: true,
})
);
app.options(
'*',
cors({
origin: true,
optionsSuccessStatus: 200,
credentials: true,
})
);
Can refer the code below for the same. Source: Academind/node-restful-api
const express = require('express');
const app = express();
//acts as a middleware
//to handle CORS Errors
app.use((req, res, next) => { //doesn't send response just adjusts it
res.header("Access-Control-Allow-Origin", "*") //* to give access to any origin
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Authorization" //to give access to all the headers provided
);
if(req.method === 'OPTIONS'){
res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, GET'); //to give access to all the methods provided
return res.status(200).json({});
}
next(); //so that other routes can take over
})
The easiest answer is to just use the cors package.
const cors = require('cors');
const app = require('express')();
app.use(cors());
That will enable CORS across the board. If you want to learn how to enable CORS without outside modules, all you really need is some Express middleware that sets the 'Access-Control-Allow-Origin' header. That's the minimum you need to allow cross-request domains from a browser to your server.
app.options('*', (req, res) => {
res.set('Access-Control-Allow-Origin', '*');
res.send('ok');
});
app.use((req, res) => {
res.set('Access-Control-Allow-Origin', '*');
});
My simplest solution with Express 4.2.0 (EDIT: Doesn't seem to work in 4.3.0) was:
function supportCrossOriginScript(req, res, next) {
res.status(200);
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Content-Type");
// res.header("Access-Control-Allow-Headers", "Origin");
// res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
// res.header("Access-Control-Allow-Methods","POST, OPTIONS");
// res.header("Access-Control-Allow-Methods","POST, GET, OPTIONS, DELETE, PUT, HEAD");
// res.header("Access-Control-Max-Age","1728000");
next();
}
// Support CORS
app.options('/result', supportCrossOriginScript);
app.post('/result', supportCrossOriginScript, function(req, res) {
res.send('received');
// do stuff with req
});
I suppose doing app.all('/result', ...) would work too...
Below worked for me, hope it helps someone!
const express = require('express');
const cors = require('cors');
let app = express();
app.use(cors({ origin: true }));
Got reference from https://expressjs.com/en/resources/middleware/cors.html#configuring-cors
Try this in your main js file:
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Authorization, X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Allow-Request-Method"
);
res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, DELETE");
res.header("Allow", "GET, POST, OPTIONS, PUT, DELETE");
next();
});
This should solve your problem
using CORS package. and put this parameters:
cors({credentials: true, origin: true, exposedHeaders: '*'})
In typescript, if you want to use the node.js package cors
/**
* app.ts
* If you use the cors library
*/
import * as express from "express";
[...]
import * as cors from 'cors';
class App {
public express: express.Application;
constructor() {
this.express = express();
[..]
this.handleCORSErrors();
}
private handleCORSErrors(): any {
const corsOptions: cors.CorsOptions = {
origin: 'http://example.com',
optionsSuccessStatus: 200
};
this.express.use(cors(corsOptions));
}
}
export default new App().express;
If you don't want to use third part libraries for cors error handling, you need to change the handleCORSErrors() method.
/**
* app.ts
* If you do not use the cors library
*/
import * as express from "express";
[...]
class App {
public express: express.Application;
constructor() {
this.express = express();
[..]
this.handleCORSErrors();
}
private handleCORSErrors(): any {
this.express.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, GET, DELETE"
);
return res.status(200).json({});
}
next(); // send the request to the next middleware
});
}
}
export default new App().express;
For using the app.ts file
/**
* server.ts
*/
import * as http from "http";
import app from "./app";
const server: http.Server = http.createServer(app);
const PORT: any = process.env.PORT || 3000;
server.listen(PORT);
Using Express Middleware works great for me. If you are already using Express, just add the following middleware rules. It should start working.
app.all("/api/*", function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With");
res.header("Access-Control-Allow-Methods", "GET, PUT, POST");
return next();
});
app.all("/api/*", function(req, res, next) {
if (req.method.toLowerCase() !== "options") {
return next();
}
return res.send(204);
});
Reference
If you want to get CORS working without the cors NPM package (for the pure joy of learning!), you can definitely handle OPTIONS calls yourself. Here's what worked for me:
app.options('*', (req, res) => {
res.writeHead(200, '', {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS',
}).end();
});
Nice and simple, right? Notice the use of res.writeHead() instead of res.header(), which I am unfamiliar with.
I found it to be extremely easy to do this with the npm request package (https://www.npmjs.com/package/request)
Then I based my solution on this post http://blog.javascripting.com/2015/01/17/dont-hassle-with-cors/
'use strict'
const express = require('express');
const request = require('request');
let proxyConfig = {
url : {
base: 'http://servertoreach.com?id=',
}
}
/* setting up and configuring node express server for the application */
let server = express();
server.set('port', 3000);
/* methods forwarded to the servertoreach proxy */
server.use('/somethingElse', function(req, res)
{
let url = proxyConfig.url.base + req.query.id;
req.pipe(request(url)).pipe(res);
});
/* start the server */
server.listen(server.get('port'), function() {
console.log('express server with a proxy listening on port ' + server.get('port'));
});
This is similiar to Pat's answer with the difference that I finish with res.sendStatus(200); instead of next();
The code will catch all the requests of the method type OPTIONS and send back access-control-headers.
app.options('/*', (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');
res.sendStatus(200);
});
The code accepts CORS from all origins as requested in the question. However, it would be better to replace the * with a specific origin i.e. http://localhost:8080 to prevent misuse.
Since we use the app.options-method instead of the app.use-method we don't need to make this check:
req.method === 'OPTIONS'
which we can see in some of the other answers.
I found the answer here: http://johnzhang.io/options-request-in-express.
The simplest approach is install the cors module in your project using:
npm i --save cors
Then in your server file import it using the following:
import cors from 'cors';
Then simply use it as a middleware like this:
app.use(cors());
Hope this helps!
simple is hard:
let my_data = []
const promise = new Promise(async function (resolve, reject) {
axios.post('https://cors-anywhere.herokuapp.com/https://maps.googleapis.com/maps/api/directions/json?origin=33.69057660000001,72.9782724&destination=33.691478,%2072.978594&key=AIzaSyApzbs5QDJOnEObdSBN_Cmln5ZWxx323vA'
, { 'Origin': 'https://localhost:3000' })
.then(function (response) {
console.log(`axios response ${response.data}`)
const my_data = response.data
resolve(my_data)
})
.catch(function (error) {
console.log(error)
alert('connection error')
})
})
promise.then(data => {
console.log(JSON.stringify(data))
})
If your Express Server has Authorization enabled, you can achieve that like this
const express = require('express');
const app=express();
const cors=require("cors");
app.use(cors({
credentials: true, // for authorization
}));
...
We can avoid CORS and forward the requests to the other server instead:
// config:
var public_folder = __dirname + '/public'
var apiServerHost = 'http://other.server'
// code:
console.log("starting server...");
var express = require('express');
var app = express();
var request = require('request');
// serve static files
app.use(express.static(public_folder));
// if not found, serve from another server
app.use(function(req, res) {
var url = apiServerHost + req.url;
req.pipe(request(url)).pipe(res);
});
app.listen(80, function(){
console.log("server ready");
});

Why doesn't adding CORS headers to an OPTIONS route allow browsers to access my API?

I am trying to support CORS in my Node.js application that uses the Express.js web framework. I have read a Google group discussion about how to handle this, and read a few articles about how CORS works. First, I did this (code is written in CoffeeScript syntax):
app.options "*", (req, res) ->
res.header 'Access-Control-Allow-Origin', '*'
res.header 'Access-Control-Allow-Credentials', true
# try: 'POST, GET, PUT, DELETE, OPTIONS'
res.header 'Access-Control-Allow-Methods', 'GET, OPTIONS'
# try: 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept'
res.header 'Access-Control-Allow-Headers', 'Content-Type'
# ...
It doesn't seem to work. It seems like my browser (Chrome) is not sending the initial OPTIONS request. When I just updated the block for the resource I need to submit a cross-origin GET request to:
app.get "/somethingelse", (req, res) ->
# ...
res.header 'Access-Control-Allow-Origin', '*'
res.header 'Access-Control-Allow-Credentials', true
res.header 'Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS'
res.header 'Access-Control-Allow-Headers', 'Content-Type'
# ...
It works (in Chrome). This also works in Safari.
I have read that...
In a browser implementing CORS, each cross-origin GET or POST request is preceded by an OPTIONS request that checks whether the GET or POST is OK.
So my main question is, how come this doesn't seem to happen in my case? Why isn't my app.options block called? Why do I need to set the headers in my main app.get block?
I found the easiest way is to use the node.js package cors. The simplest usage is:
var cors = require('cors')
var app = express()
app.use(cors())
There are, of course many ways to configure the behaviour to your needs; the page linked above shows a number of examples.
Try passing control to the next matching route. If Express is matching app.get route first, then it won't continue onto the options route unless you do this (note use of next):
app.get('somethingelse', (req, res, next) => {
//..set headers etc.
next();
});
In terms of organising the CORS stuff, I put it in a middleware which is working well for me:
// CORS middleware
const allowCrossDomain = (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(() => {
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: `cool beans` }));
app.use(express.methodOverride());
// CORS middleware
app.use(allowCrossDomain);
app.use(app.router);
app.use(express.static(`public`));
});
To answer your main question, the CORS spec only requires the OPTIONS call to precede the POST or GET if the POST or GET has any non-simple content or headers in it.
Content-Types that require a CORS pre-flight request (the OPTIONS call) are any Content-Type except the following:
application/x-www-form-urlencoded
multipart/form-data
text/plain
Any other Content-Types apart from those listed above will trigger a pre-flight request.
As for Headers, any Request Headers apart from the following will trigger a pre-flight request:
Accept
Accept-Language
Content-Language
Content-Type
DPR
Save-Data
Viewport-Width
Width
Any other Request Headers will trigger the pre-flight request.
So, you could add a custom header such as: x-Trigger: CORS, and that should trigger the pre-flight request and hit the OPTIONS block.
See MDN Web API Reference - CORS Preflighted requests
To stay in the same idea of routing. I use this code :
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
Similar to http://enable-cors.org/server_expressjs.html example
do
npm install cors --save
and just add these lines in your main file where your request going (keep it before any route).
const cors = require('cors');
const express = require('express');
let app = express();
app.use(cors());
app.options('*', cors());
I have made a more complete middleware suitable for express or connect. It supports OPTIONS requests for preflight checking. Note that it will allow CORS access to anything, you might want to put in some checks if you want to limit access.
app.use(function(req, res, next) {
var oneof = false;
if(req.headers.origin) {
res.header('Access-Control-Allow-Origin', req.headers.origin);
oneof = true;
}
if(req.headers['access-control-request-method']) {
res.header('Access-Control-Allow-Methods', req.headers['access-control-request-method']);
oneof = true;
}
if(req.headers['access-control-request-headers']) {
res.header('Access-Control-Allow-Headers', req.headers['access-control-request-headers']);
oneof = true;
}
if(oneof) {
res.header('Access-Control-Max-Age', 60 * 60 * 24 * 365);
}
// intercept OPTIONS method
if (oneof && req.method == 'OPTIONS') {
res.send(200);
}
else {
next();
}
});
Do something like this:
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();
});
install cors module of expressjs. you can follow these steps >
Installation
npm install cors
Simple Usage (Enable All CORS Requests)
var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());
for more details go to https://github.com/expressjs/cors
Testing done with express + node + ionic running in differente ports.
Localhost:8100
Localhost:5000
// CORS (Cross-Origin Resource Sharing) headers to support Cross-site HTTP requests
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
});
first simply install cors in your project.
Take terminal(command prompt) and cd to your project directory and run the below command:
npm install cors --save
Then take the server.js file and change the code to add the following in it:
var cors = require('cors');
var app = express();
app.use(cors());
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'DELETE, PUT, GET, POST');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
This worked for me..
Some time ago, I faced this problem so I did this to allow CORS in my nodejs app:
First you need to install cors by using below command :
npm install cors --save
Now add the following code to your app starting file like ( app.js or server.js)
var express = require('express');
var app = express();
var cors = require('cors');
var bodyParser = require('body-parser');
//enables cors
app.use(cors({
'allowedHeaders': ['sessionId', 'Content-Type'],
'exposedHeaders': ['sessionId'],
'origin': '*',
'methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
'preflightContinue': false
}));
require('./router/index')(app);
This works for me, as its an easy implementation inside the routes, im using meanjs and its working fine, safari, chrome, etc.
app.route('/footer-contact-form').post(emailer.sendFooterMail).options(function(req,res,next){
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
return res.send(200);
});
If you want to make it controller specific, you can use:
res.setHeader("X-Frame-Options", "ALLOWALL");
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST, GET");
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
Please note that this will also allow iframes.
In my index.js I added:
app.use((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, PUT, DELETE, OPTIONS");
next();
})
cors package is recommended way to for solving the CORS policy issue in express.js, but you also need to make sure to enable it for app.options as well, like below:
const cors = require('cors');
// enable cors
app.use(
cors({
origin: true,
optionsSuccessStatus: 200,
credentials: true,
})
);
app.options(
'*',
cors({
origin: true,
optionsSuccessStatus: 200,
credentials: true,
})
);
Can refer the code below for the same. Source: Academind/node-restful-api
const express = require('express');
const app = express();
//acts as a middleware
//to handle CORS Errors
app.use((req, res, next) => { //doesn't send response just adjusts it
res.header("Access-Control-Allow-Origin", "*") //* to give access to any origin
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Authorization" //to give access to all the headers provided
);
if(req.method === 'OPTIONS'){
res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, GET'); //to give access to all the methods provided
return res.status(200).json({});
}
next(); //so that other routes can take over
})
The easiest answer is to just use the cors package.
const cors = require('cors');
const app = require('express')();
app.use(cors());
That will enable CORS across the board. If you want to learn how to enable CORS without outside modules, all you really need is some Express middleware that sets the 'Access-Control-Allow-Origin' header. That's the minimum you need to allow cross-request domains from a browser to your server.
app.options('*', (req, res) => {
res.set('Access-Control-Allow-Origin', '*');
res.send('ok');
});
app.use((req, res) => {
res.set('Access-Control-Allow-Origin', '*');
});
My simplest solution with Express 4.2.0 (EDIT: Doesn't seem to work in 4.3.0) was:
function supportCrossOriginScript(req, res, next) {
res.status(200);
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Content-Type");
// res.header("Access-Control-Allow-Headers", "Origin");
// res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
// res.header("Access-Control-Allow-Methods","POST, OPTIONS");
// res.header("Access-Control-Allow-Methods","POST, GET, OPTIONS, DELETE, PUT, HEAD");
// res.header("Access-Control-Max-Age","1728000");
next();
}
// Support CORS
app.options('/result', supportCrossOriginScript);
app.post('/result', supportCrossOriginScript, function(req, res) {
res.send('received');
// do stuff with req
});
I suppose doing app.all('/result', ...) would work too...
Below worked for me, hope it helps someone!
const express = require('express');
const cors = require('cors');
let app = express();
app.use(cors({ origin: true }));
Got reference from https://expressjs.com/en/resources/middleware/cors.html#configuring-cors
Try this in your main js file:
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Authorization, X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Allow-Request-Method"
);
res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, DELETE");
res.header("Allow", "GET, POST, OPTIONS, PUT, DELETE");
next();
});
This should solve your problem
using CORS package. and put this parameters:
cors({credentials: true, origin: true, exposedHeaders: '*'})
In typescript, if you want to use the node.js package cors
/**
* app.ts
* If you use the cors library
*/
import * as express from "express";
[...]
import * as cors from 'cors';
class App {
public express: express.Application;
constructor() {
this.express = express();
[..]
this.handleCORSErrors();
}
private handleCORSErrors(): any {
const corsOptions: cors.CorsOptions = {
origin: 'http://example.com',
optionsSuccessStatus: 200
};
this.express.use(cors(corsOptions));
}
}
export default new App().express;
If you don't want to use third part libraries for cors error handling, you need to change the handleCORSErrors() method.
/**
* app.ts
* If you do not use the cors library
*/
import * as express from "express";
[...]
class App {
public express: express.Application;
constructor() {
this.express = express();
[..]
this.handleCORSErrors();
}
private handleCORSErrors(): any {
this.express.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, GET, DELETE"
);
return res.status(200).json({});
}
next(); // send the request to the next middleware
});
}
}
export default new App().express;
For using the app.ts file
/**
* server.ts
*/
import * as http from "http";
import app from "./app";
const server: http.Server = http.createServer(app);
const PORT: any = process.env.PORT || 3000;
server.listen(PORT);
Using Express Middleware works great for me. If you are already using Express, just add the following middleware rules. It should start working.
app.all("/api/*", function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With");
res.header("Access-Control-Allow-Methods", "GET, PUT, POST");
return next();
});
app.all("/api/*", function(req, res, next) {
if (req.method.toLowerCase() !== "options") {
return next();
}
return res.send(204);
});
Reference
If you want to get CORS working without the cors NPM package (for the pure joy of learning!), you can definitely handle OPTIONS calls yourself. Here's what worked for me:
app.options('*', (req, res) => {
res.writeHead(200, '', {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS',
}).end();
});
Nice and simple, right? Notice the use of res.writeHead() instead of res.header(), which I am unfamiliar with.
I found it to be extremely easy to do this with the npm request package (https://www.npmjs.com/package/request)
Then I based my solution on this post http://blog.javascripting.com/2015/01/17/dont-hassle-with-cors/
'use strict'
const express = require('express');
const request = require('request');
let proxyConfig = {
url : {
base: 'http://servertoreach.com?id=',
}
}
/* setting up and configuring node express server for the application */
let server = express();
server.set('port', 3000);
/* methods forwarded to the servertoreach proxy */
server.use('/somethingElse', function(req, res)
{
let url = proxyConfig.url.base + req.query.id;
req.pipe(request(url)).pipe(res);
});
/* start the server */
server.listen(server.get('port'), function() {
console.log('express server with a proxy listening on port ' + server.get('port'));
});
This is similiar to Pat's answer with the difference that I finish with res.sendStatus(200); instead of next();
The code will catch all the requests of the method type OPTIONS and send back access-control-headers.
app.options('/*', (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');
res.sendStatus(200);
});
The code accepts CORS from all origins as requested in the question. However, it would be better to replace the * with a specific origin i.e. http://localhost:8080 to prevent misuse.
Since we use the app.options-method instead of the app.use-method we don't need to make this check:
req.method === 'OPTIONS'
which we can see in some of the other answers.
I found the answer here: http://johnzhang.io/options-request-in-express.
The simplest approach is install the cors module in your project using:
npm i --save cors
Then in your server file import it using the following:
import cors from 'cors';
Then simply use it as a middleware like this:
app.use(cors());
Hope this helps!
simple is hard:
let my_data = []
const promise = new Promise(async function (resolve, reject) {
axios.post('https://cors-anywhere.herokuapp.com/https://maps.googleapis.com/maps/api/directions/json?origin=33.69057660000001,72.9782724&destination=33.691478,%2072.978594&key=AIzaSyApzbs5QDJOnEObdSBN_Cmln5ZWxx323vA'
, { 'Origin': 'https://localhost:3000' })
.then(function (response) {
console.log(`axios response ${response.data}`)
const my_data = response.data
resolve(my_data)
})
.catch(function (error) {
console.log(error)
alert('connection error')
})
})
promise.then(data => {
console.log(JSON.stringify(data))
})
If your Express Server has Authorization enabled, you can achieve that like this
const express = require('express');
const app=express();
const cors=require("cors");
app.use(cors({
credentials: true, // for authorization
}));
...
We can avoid CORS and forward the requests to the other server instead:
// config:
var public_folder = __dirname + '/public'
var apiServerHost = 'http://other.server'
// code:
console.log("starting server...");
var express = require('express');
var app = express();
var request = require('request');
// serve static files
app.use(express.static(public_folder));
// if not found, serve from another server
app.use(function(req, res) {
var url = apiServerHost + req.url;
req.pipe(request(url)).pipe(res);
});
app.listen(80, function(){
console.log("server ready");
});

Resources