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

37

767

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?

Amphithecium answered 15/8, 2011 at 16:53 Comment(2)
This answer maybe useful: https://mcmap.net/q/48595/-access-control-allow-origin-issue-in-angular-2Alverson
Did you declare app.options('*', cors()); before all routes?Varityper
F
221

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:

  1. application/x-www-form-urlencoded
  2. multipart/form-data
  3. 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:

  1. Accept
  2. Accept-Language
  3. Content-Language
  4. Content-Type
  5. DPR
  6. Save-Data
  7. Viewport-Width
  8. 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

Frederiksberg answered 20/12, 2011 at 8:32 Comment(4)
Can you provide an example?Bullhorn
The page I linked to seems to have a number of examples. Could you tell me what example you think is missing?Frederiksberg
In general though, link-only answers are fragile because they could, at any moment, be broken. That said, this answer seems good enough in that it's highlighting the general conditions under which OPTIONS blocks don't send. Would be nice if it had the list of accepted HEADERS, or which content-types require OPTIONS, etc but it's a good startCompilation
Great answer thank you, but adding a custom x-Trigger header only to trigger the pre-flight sounds odd to me, is that suggested only for "educational" purposes here or it's something actually useful?Wyman
A
728

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.

Admiralty answered 7/2, 2014 at 8:16 Comment(8)
It fails for me when I use it with credentials. :( Everything else worked like a charm.. But its of no use to me if it fails withCredentials set to trueOceangoing
Its working fine for ajax request. I want CORS implementation for Script Tags and iFrame because in these requests the Origin is not present in the request header :( How to implement this ?Knavery
You need to also set cors({credentials: true, origin: true})Limicolous
how do you enable options preflight here?Sofa
@Limicolous Never, ever use cors({credentials: true, origin: true})! It amounts to voiding the same-origin policy. Very insecure.Communitarian
@Arnout Engelen I have a public fetch API. But some people were telling to enable CORS as it blocks their requests. I know there is an npm package called cors. But I saw that many Public APIs do not have CORS enabled. I also read some articles about the security risks in CORS. I was asking that will it be wrong to enable CORS. Few people are calling the API from client-side code that is running in the browsers. Any suggestion is gratefully accepted.Quixotic
@DronBhattacharya the question you are responding to is about how to enable CORS. Your question is about in which cases it is OK to enable CORS. I think that is indeed a good and interesting one, but is too 'big' to try to answer in the comments here - it should be a separate question.Iolanthe
@ArnoutEngelen Please answer these: q 1 and q 2. They are related to the above comment. If the questions are not clear, help improving themQuixotic
L
477

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`));
});
Lingonberry answered 15/8, 2011 at 19:45 Comment(17)
Thanks for suggesting this approach. Looks cleaner than having to add the setting of the headers in each of my resource. But I was hoping someone could explain why the preflight request using the OPTIONS method was not performed at all.Amphithecium
Updated the answer, hope that helps.Lingonberry
I believe OPTIONS happens before a GET, whereas if you're doing a POST - there is no OPTIONS request...Slime
Is config.allowedDomains a comma-delimited string or an array?Cloakanddagger
I realize that app.use(allowCrossDomain); must put before app.use(app.router);. Could you please explain why? Thanks.Feathery
config.allowedDomains should be a space separated arrayKimberykimble
I ended up using something similar. Did anyone notice that the OPTIONS 204 creates an extra session since it doesn't send any cookies?Foreshank
The extra session was removed by simply rearranging the express middleware order. On another note, this needs a little more security. if the origin is not in the allowed domain then the request is still processed, only the browser won't be able to see it plus the origin can be spoofed. My advice would be to do a check and if the origin is not in the allowed list then return 403 immediately. Also is any sensitive information is being served, validate the user via a session.Foreshank
@Kimberykimble Could you please explain what do you mean by space separated array?Rolan
@pootzko I realise thats a bit unclear, it should be a string, with spaces, eg, "example.com test.com anotherdomain.com"Kimberykimble
@Kimberykimble Thanks for the reply. Although I tried that one out, and it didn't work for me. What did was something like this: "example.com" || "test.com" || "whatever.com". Basically chained or's.Rolan
for debug purposes use res.header('Access-Control-Allow-Origin', req.headers.origin); as res.header('Access-Control-Allow-Origin', config.allowedDomains);Branching
This worked really well for me, using something like config = { allowedDomains : ["allowed.com"] };Mashburn
I edited the answer and removed config.allowedDomains. As stated by the CORS spec, you can have only one domain in the Access-Control-Allow-Origin header (or * or null).Macintyre
app.configure is deprecated expressjs.com/ru/guide/migrating-4.html#other-changesHershberger
you should also set res.header('Access-Control-Allow-Credentials', 'true');Birdella
This doesn't respond to OPTIONS requests for me - i get a 404Hypermeter
F
221

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:

  1. application/x-www-form-urlencoded
  2. multipart/form-data
  3. 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:

  1. Accept
  2. Accept-Language
  3. Content-Language
  4. Content-Type
  5. DPR
  6. Save-Data
  7. Viewport-Width
  8. 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

Frederiksberg answered 20/12, 2011 at 8:32 Comment(4)
Can you provide an example?Bullhorn
The page I linked to seems to have a number of examples. Could you tell me what example you think is missing?Frederiksberg
In general though, link-only answers are fragile because they could, at any moment, be broken. That said, this answer seems good enough in that it's highlighting the general conditions under which OPTIONS blocks don't send. Would be nice if it had the list of accepted HEADERS, or which content-types require OPTIONS, etc but it's a good startCompilation
Great answer thank you, but adding a custom x-Trigger header only to trigger the pre-flight sounds odd to me, is that suggested only for "educational" purposes here or it's something actually useful?Wyman
B
134

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

Brenna answered 24/2, 2012 at 10:46 Comment(3)
This goes in the grunt.js file?Thermic
What about preflight?Auricula
No @OliverDixon, this is on the server sidePolymerous
A
100

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());
Ap answered 21/7, 2016 at 9:26 Comment(1)
app.options('*', cors()) // include before other routesI
K
64

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();
    }
});
Kimberykimble answered 30/10, 2012 at 21:49 Comment(6)
Hey there, I came across your solution and was wondering if the 'oneof' flag should be set false if one of the headers wasn't detected?Peng
Some requests will not have all the headers. Specifically a GET request will be sent by the browser, and when it doesn't get a correct allow-origin response an error is given to js. Whereas for a POST request, the OPTIONS request is first sent, with the allow-method header, and only afterwards, the actual POST request will be sent.Kimberykimble
Ah, I see. Thanks. Did you ever run into trouble by not putting res.send(200) in there if the req method was 'options'?Peng
I dont think i have tried sending something else, I would imagine any other response will cause the browser to refuse the request that it is preflighting.Kimberykimble
works like charm, i would just add a list of authorized domains for more securityDilan
@Shide completely agree, you really ought to be checking the origin domain is one you trustKimberykimble
B
43

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();
});
Brewhouse answered 3/1, 2016 at 8:24 Comment(0)
S
40

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

Senhorita answered 15/6, 2016 at 20:37 Comment(2)
TypeError: Cannot read property 'headers' of undefined The most basic app setup.Thermic
Are you sure you have request object ? :)Shrewsbury
K
23

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();
});
Kinch answered 8/11, 2014 at 20:35 Comment(1)
In which file do we need to add this lines?Eastward
B
22

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..

Buddhism answered 5/9, 2017 at 9:8 Comment(3)
You don't need cors if you're doing the res.header stuff. cors is a library that handles all that for you. Delete your first & 3rd lines (AKA everything with cors) and you'll find that it still works.Gerlac
heck i'm pretty sure all you really need is this line res.header("Access-Control-Allow-Origin", "*");Gerlac
though do keep in mind that you're compromising your security by doing that. :)Gerlac
H
12

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);
Hadwyn answered 24/1, 2017 at 10:19 Comment(1)
tried this after installing cors. Cors is not a functionInpour
V
11

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

    });
Vaccine answered 24/8, 2015 at 20:13 Comment(0)
H
11

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.

Hudnall answered 5/1, 2018 at 22:1 Comment(0)
D
8

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();
}) 
Deciduous answered 17/6, 2019 at 10:47 Comment(1)
I should comment that Access-Control-Allow-Origin = * means that you won't be able to send Cookies to the server, they will be rejected by the CORS Policy - source : developer.mozilla.org/en-US/docs/Web/HTTP/… . So, dont use this if you want to use cookies.Petulia
M
8

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,
  })
);
Meeting answered 20/6, 2021 at 14:39 Comment(0)
K
6

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
})
Keeley answered 25/9, 2018 at 12:29 Comment(1)
I saw many answer and this have something which is importan, I tried to use this part of the code after some other configurations and it didn't work and for some reason, I tried putting the code after app const app = express(); and works! I think is important to mention it.Recreation
G
6

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', '*');
});
Gene answered 15/11, 2019 at 15:24 Comment(0)
I
4

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...

Illuminometer answered 5/5, 2014 at 23:47 Comment(0)
N
4

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

Ngocnguyen answered 15/3, 2019 at 9:2 Comment(2)
What file does that go in? peanutbutter.js?Mcmanus
not sure about peanutbutter.js, for me it is express.js. basically, it should be the file where you require your express app, initialize it, and require route files.Ngocnguyen
C
3

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

Conflagration answered 10/4, 2020 at 20:20 Comment(0)
C
3

using CORS package. and put this parameters:

cors({credentials: true, origin: true, exposedHeaders: '*'})
Certificate answered 26/10, 2020 at 11:25 Comment(1)
The exact answer I was looking to allow my auth-token header to be visible in response headerLoeb
U
3

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.

Universalism answered 11/4, 2021 at 4:51 Comment(0)
S
2

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);
Swabber answered 9/7, 2018 at 9:41 Comment(2)
"If the server is written in typescript" — It isn't. The question says it is written in CoffeeScript.Pelag
@Pelag I just wanted to show an alternative in typesript, hoping that this could help somebody.Swabber
N
2

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

Nanon answered 29/8, 2018 at 18:29 Comment(0)
C
2

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
}));
...
Culmiferous answered 21/12, 2021 at 20:6 Comment(0)
G
1

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'));
});
Guncotton answered 10/2, 2016 at 13:6 Comment(0)
E
1

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.

Endorse answered 17/1, 2019 at 10:39 Comment(0)
L
1

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!

Libration answered 20/4, 2019 at 3:53 Comment(0)
S
1

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))
})
Schellens answered 3/3, 2020 at 10:13 Comment(0)
S
0

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");
});
Shroff answered 15/5, 2016 at 8:45 Comment(1)
this does not answer the question askedDisinterested
G
0

I used the following steps to my web app and I had success:

Add the cors package to the express:

npm install cors --save

Add following lines after the bodyParser configuration. I had some troubles adding before bodyParser:

 // enable cors to the server
const corsOpt = {
    origin: process.env.CORS_ALLOW_ORIGIN || '*', // this work well to configure origin url in the server
    methods: ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS'], // to works well with web app, OPTIONS is required
    allowedHeaders: ['Content-Type', 'Authorization'] // allow json and token in the headers
};
app.use(cors(corsOpt)); // cors for all the routes of the application
app.options('*', cors(corsOpt)); // automatic cors gen for HTTP verbs in all routes, This can be redundant but I kept to be sure that will always work.
Grassofparnassus answered 14/6, 2018 at 13:36 Comment(0)
W
0

If i were you @OP i would change my programming paradigm.

assuming you are getting these CORS blocked because you are making requests to localhost or something similar.

Eventually if you are going to deploy to production optoins like Google Cloud Platform or Heroku or , you will no have to worry about CORS like allow origin or whatever when in production.

so when testing the server just use postman and you will not get CORS blocked, after that deploy your server and then work on your client.

Whitherward answered 17/8, 2019 at 17:45 Comment(0)
P
0

You can use Express middleware, block your domain and methods.

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", process.env.DOMAIN); // update to match the domain you will make the request from
  res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE");
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept"
  );
  next();
});
Pilau answered 6/9, 2019 at 11:22 Comment(0)
T
0

With reactstrap "npm run start" at 3000 and a nodejs express server at 3001 in 2023 the following in the server.js was working before all other routes :

app.use(function (req, res, next) {
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Headers", "Access-Control-Allow-Origin");
    res.header("Access-Control-Allow-Origin", "*"); // update to match the domain you will make the request from
    next();
});
Traweek answered 30/10, 2023 at 10:45 Comment(0)
A
-1

Below code will work ,but first install cors by:

npm install --save cors

Then:

module.exports = function(app) { 
var express = require("express");
var cors = require('cors');
var router = express.Router();
app.use(cors());

app.post("/movies",cors(), function(req, res) { 
res.send("test");
});
Ashely answered 2/10, 2018 at 13:40 Comment(0)
P
-1

using nodejs without express/external libraries I made use of the below method within my server.js file. The key parts here are getting the origin from the request header then allowing it in the server response at which point we can set the header that will be returned including the allowed origin if a match is found.

    **const origin = req.headers.origin;**

      let decoder = new StringDecoder('utf-8');
      let buffer = '';
      req.on('data', function (data) {
        buffer += decoder.write(data);
      });
      req.on('end', function () {
        buffer += decoder.end();

        let chosenHandler = typeof (server.router[trimmedPath]) !== 'undefined' ? server.router[trimmedPath] : handlers.notFound;

const data = { ....data object vars}

// should be wrapped in try catch block
      chosenHandler(data, function (statusCode, payload, contentType) {
        server.processHandlerResponse(res, method, trimmedPath, statusCode, payload, contentType, **origin**);


server.processHandlerResponse = function (res, method, trimmedPath, statusCode, payload, contentType, origin) {
  contentType = typeof (contentType) == 'string' ? contentType : 'json';

  statusCode = typeof (statusCode) == 'number' ? statusCode : 200;

  let payloadString = '';
  if (contentType == 'json') {
    res.setHeader('Content-Type', 'application/json');

    const allowedOrigins = ['https://www.domain1.com', 'https://someotherdomain','https://yetanotherdomain',
    ...// as many as you need
  ];
    **if (allowedOrigins.indexOf(origin) > -1) {
        res.setHeader('Access-Control-Allow-Origin', origin);
    }**
    payload = typeof (payload) == 'object' ? payload : {};
    payloadString = JSON.stringify(payload);
  }

... //  if (other content type) ...rinse and repeat..
Periderm answered 2/3, 2019 at 7:40 Comment(0)
E
-3

/*first of all, and this might be the problem amongst junior devs out there, like myself: make sure to use "lambda" >>>> "`" and not "'" in your fetch method! */

``` const response = await fetch(https://api....);

/plus, the following article is highly recommended: https://developer.edamam.com/api/faq/

Elvia answered 1/2, 2020 at 11:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.