Allow CORS REST request to a Express/Node.js application on Heroku
Solution 1
I've cheked your code on a clean ExpressJS app and it works just fine.
Try move your app.use(allowCrossDomain)
to the top of configure function.
Solution 2
I'm adding this as an answer only because the original post was put in as a comment and as such it got overlooked by yours truly the first time I went over this page.
As @ConnorLeech points out in his comment to the accepted answer above, there is a very handy npm package called, not surprisingly, cors. It's use is as simple as var cors = require('cors'); app.use(cors());
(again, cribbed from Mr. Leech's answer) and can also be applied in a stricter, more configurable fashion as outlined in their docs.
It may also be worth pointing out that the original comment I refer to above was made in 2014. It's 2019 now and looking at the npm package's github page the repo was updated as recently as nine days ago.
Solution 3
for supporting cookies withCredentials you need this line
xhr.withCredentials = true;
In the Express Server add this block before all the other
`app.all('*', function(req, res, next) {
var origin = req.get('origin');
res.header('Access-Control-Allow-Origin', origin);
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
});`
Solution 4
It could not be the case for most people browsing this question but I had this exact same problem and the solution was not related to CORS
.
Turns out that JSON Web Token secret string
was not defined in the environment variables, so the token could not be signed.
This caused to any POST
request that relies on checking or signing a token to get a timeout and return a 503
error, telling the browser that there's something wrong in CORS
, which it's not.
Adding the environment variable in Heroku solved the issue.
I hope this helps someone.
Solution 5
Follow the below steps:
npm install cors --save
Inside your root js file:
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
Related videos on Youtube
Jamie Folsom
Digital Humanities web application developer and software architect, working with faculty and staff at institutions of higher learning in the US, Canada and Europe (so far). Primarily using ruby, rails, javascript, postgresql and related technologies.
Updated on April 22, 2021Comments
-
Jamie Folsom about 3 years
I've written a REST API on the express framework for node.js that works for requests from the js console in Chrome, and URL bar, etc. I'm now trying to get it working for requests from another app, on a different domain (CORS).
The first request, made automatically by the javascript front end, is to /api/search?uri=, and appears to be failing on the "preflight" OPTIONS request.
In my express app, I am adding CORS headers, using:
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(); } };
and:
app.configure(function () { app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(allowCrossDomain); app.use(express.static(path.join(application_root, "public"))); app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); });
From the Chrome console I get these headers:
Request URL:http://furious-night-5419.herokuapp.com/api/search?uri=http%3A%2F%2Flocalhost%3A5000%2Fcollections%2F1%2Fdocuments%2F1
Request Method:OPTIONS
Status Code:200 OK
Request Headers
Accept:*/* Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3 Accept-Encoding:gzip,deflate,sdch Accept-Language:en-US,en;q=0.8 Access-Control-Request-Headers:origin, x-annotator-auth-token, accept Access-Control-Request-Method:GET Connection:keep-alive Host:furious-night-5419.herokuapp.com Origin:http://localhost:5000 Referer:http://localhost:5000/collections/1/documents/1 User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.56 Safari/536.5
Query String Parameters
uri:http://localhost:5000/collections/1/documents/1
Response Headers
Allow:GET Connection:keep-alive Content-Length:3 Content-Type:text/html; charset=utf-8 X-Powered-By:Express
Does this look like a lack of proper headers being sent by the API application?
Thanks.
-
Ulysses Alves almost 8 yearsI'm getting this error in a code I didn't wrote, but I don't understand the need of a handler for the
OPTIONS
method. Could someone please help me to understand why not handling just thePOST
method instead of handling bothPOST
andOPTIONS
method? -
Danny over 5 yearsMight also want to include
PATCH
if you will use it instead ofPUT
to update a resource
-
-
Michal over 11 yearsThe reason it did is because you need to have it defined before the
app.use(app.router);
Cheers! -
Aldo over 11 yearsIn my case, next POST is not being called after sending back res.send(200) when req.method == 'OPTIONS'. am I missing anything else ?
-
Olegas over 11 years2Aldo: Code needed. May be you forgot some headers? If your client is not sending a POST after your server is correctly served a preflight OPTIONS request, try to check developer tools console. WebKit logs this kind of errors to web inspector's console.
-
Steven over 9 years@ConnorLeech Very nice. I had been doing the allowCrossDomain approach as above and was tired of dealing with all that header mgmt. Also - since we only needed CORS for dev, wasn't making any sense to devote so many cycles to figuring out what was going on. Glad there is node.js support for easily allowing this.
-
drmrbrewer over 6 years@ConnorLeech I think you should add your comment as an answer... works like a treat, and it's nice and simple
-
Alan over 6 yearsYes that was the problem with me. Could you be more specific how you solved problem. I am still in development still and am running on Express.js w/node cors package.
-
CatBrownie over 6 years@alan I was using promises to verifying the token in my application, some how if the JWT secret is not defined, the promise will never resolve, here's the code I was using if you need further reference.
-
Alan over 6 yearsThanks for responding. I will look over code. By secret I assume you are talking about the second private key. I am using oauth2.
-
alphanumeric0101 about 6 yearsI will add that any failing promise will produce this misleading error! I had to be explicit about a Node version being used or else my database calls (mongo) were simply hanging and the only thing the browser could tell me was 503 and then some Cors related silliness. This error really confused me for the longest as I had
app.use(cors());
going. -
brunelli about 3 years@CatBrownie, thanks for this answer. Exactly what I needed!