1

I am building a web application with node js on server side and angular on client.

I am running the server on different domain and client on other domain.

My server side code:

var express = require('express');
var app = express();
var http = require("http").createServer(app);
var request = require('request');

app.use(function(req, res, next) {
  console.log(req.headers);
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", 
             "Origin, X-Requested-With, Content-Type, Accept, Authorization");
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
  next();
});

app.get('/api/hello', function(req, res){
  var data = {'message': 'Server is running'}
  res.jsonp(data);
});

http.listen(5000);

and on the client side (Angular).

angular.controller('myController', function($state, $http){
  $http.get('http://localhost:5000/api/hello').success(function(response, status) {
    console.log(responce);
  }).error( function(error, status) {
    console.log(error)
  });
});

My Server is running on port 5000 and my client on port 4000 on different domains.

When I send the above request from client, I get below error in browser console,

XMLHttpRequest cannot load http://localhost:5000/api/hello. Response to preflight request doesn't pass access control check: A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://localhost:4000' is therefore not allowed access.

I have same problem with the ionic app too.

What could be the reason behind this?

I am accessing these API's from multiple domains and from different applications like mobile and web.

Håken Lid
  • 22,318
  • 9
  • 52
  • 67
NitinD
  • 489
  • 2
  • 7
  • 21
  • A pre-flight request uses the `'options'` verb instead of `'get'` so you need a handler for that. There is something about the specific request you're making (probably custom headers) that forces the use of the `'options'` preflight. – jfriend00 Jun 06 '16 at 06:42
  • try being domain specific with `Access-Control-Allow-Origin` header. – techie_28 Jun 06 '16 at 06:45
  • See [How to enable CORS in Express](http://justindavis.co/2015/08/31/CORS-in-Express/) for `OPTIONS` support. – jfriend00 Jun 06 '16 at 06:47
  • @jfriend00 I looked into your first comment, but I don't set any custom headers. – NitinD Jun 06 '16 at 06:54
  • @techie_28 I am accessing this server apis from multiple domains. So, I am not being domain specific. – NitinD Jun 06 '16 at 06:58
  • Well, there are several things that can trigger the use of the OPTIONS preflight. Your error message makes it appear that is being triggered, but your server does not support it so you are denied access. That's your first issue to solve. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests for details on what can trigger it or implement support for it. – jfriend00 Jun 06 '16 at 07:01
  • @nitinmegamind I suggested that for the testing purpose only.The error is self describing.Wildcard `*` is disallowed in case you use credentials. – techie_28 Jun 06 '16 at 07:31
  • @techie_28 I have added a domain specific too, but still the same error. – NitinD Jun 06 '16 at 08:42
  • @nitinmegamind I expected error to say something else in that case.You mentioned the specific domain instead of a `*`? – techie_28 Jun 06 '16 at 09:35
  • I mentioned **http://localhost:4000** instead of *. – NitinD Jun 06 '16 at 10:38
  • 1
    @nitinmegamind seems you are facing this possibly : http://stackoverflow.com/questions/10883211/deadly-cors-when-http-localhost-is-the-origin – techie_28 Jun 07 '16 at 05:38
  • @techie_28 I have tried with a server too. Facing the same problem. – NitinD Jun 09 '16 at 09:12
  • @nitinmegamind both of them are on a valid server & are you using wildcard still?If so try with specific value in there for once.Is there no change in the console error? – techie_28 Jun 09 '16 at 09:51
  • @nitinmegamind are you really using credentials anywhere? – techie_28 Jun 09 '16 at 10:16
  • @techie_28 I am not using credentials. But I am using token for some apis to authenticate the user. Is that the problem? – NitinD Jun 10 '16 at 19:02
  • @nitinmegamind check this..You will have to set `withCredentials` to false on your client side. http://stackoverflow.com/questions/34078676/access-control-allow-origin-not-allowed-when-credentials-flag-is-true-but – techie_28 Jun 15 '16 at 07:43

3 Answers3

1

you can use cors as like as given below:

install cors module

npm install --save cors

server code

 var express = require('express');
 var cors = require('cors');


 var app = express();     

 app.use(cors());

 // others code

Angular

angular.controller('myController', function($state, $http){

   $http
     .get('http://localhost:5000/api/hello')
     .then(function(response) {
          console.log(responce);
       }, function(error, status) {
          console.log(error)
       });
});
sabbir
  • 2,020
  • 3
  • 26
  • 48
  • 3
    Still I get the CORS error. This solution didn't work for me. Tried doing the same in angular. But no success. – NitinD Jun 06 '16 at 06:46
0

In that error, it appears as though your Access-Control-Allow-Credentials header might be to returned as true? What headers does your response contain?

Try adding res.header('Access-Control-Allow-Credentials', false); when you're adding your headers and see if that solves that particular error.

Also, is there a reason why you've included the http.createServer(app) code? ExpressJS apps are typically started by calling app.listen directly like so which could well be the issue.

app.listen(5000, function () {
  console.log('Example app listening on port 5000!');
});
Ian Belcher
  • 5,583
  • 2
  • 34
  • 43
  • Your preflight is reaching the server (or a server somewhere) as it is receiving some form of header from the preflight request (the OPTIONS request). What headers does this request receive? You can find this information in your inspector. What does visiting `http://localhost:5000/api/hello`directly in the browser return as well? – Ian Belcher Jun 06 '16 at 07:20
  • Reqeust Headers: OPTIONS /api/hello HTTP/1.1 Host: localhost:5000 Connection: keep-alive Access-Control-Request-Method: POST Origin: http://localhost:4000 Access-Control-Request-Headers: accept, content-type Accept: */* Referer: http://localhost:4000/ Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8 – NitinD Jun 06 '16 at 08:40
  • Response Headers: HTTP/1.1 200 OK X-Powered-By: Express Access-Control-Allow-Origin: * Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization Access-Control-Allow-Methods: GET,PUT,POST,DELETE,PATCH,OPTIONS Access-Control-Allow-Credentials: false Allow: GET,HEAD,POST,PUT Content-Type: text/html; charset=utf-8 Content-Length: 17 ETag: W/"11-UunX7iLX/fl1v0lmwRZzlA" Date: Mon, 06 Jun 2016 08:38:49 GMT Connection: keep-alive – NitinD Jun 06 '16 at 08:42
  • Yeah, not sure. That all looks fine. Only other thing I'd suggest is checking if you have any cookies or auth based stuff cached in your browser from other projects that the browser might be trying to send? Otherwise not sure... Good luck otherwise! – Ian Belcher Jun 06 '16 at 09:00
  • 1
    @IanBelcher this seems to be a "using localhost as origin problem".. http://stackoverflow.com/questions/10883211/deadly-cors-when-http-localhost-is-the-origin – techie_28 Jun 08 '16 at 05:21
  • @techie_28: I myself haven't used locahost for development for some time now, but that link looks like it most likely could be the cause. Good to keep that in mind for future. – Ian Belcher Jun 08 '16 at 05:42
0

in routes i made a file named as corsheaders.js which contains

module.exports = function (req, res, next) {
    if (allowedHosts.indexOf(req.headers.origin) > -1) {
        res.header('Access-Control-Allow-Origin', req.headers.origin);
        res.header('Access-Control-Allow-Credentials', true);
        res.header('Access-Control-Allow-Methods', 'GET,POST,DELETE,OPTIONS,PUT');
        res.header('Access-Control-Allow-Headers', 'Content-Type');
    }
    next();
};

here allowedHosts is an array which contains the domain which i am allowing and in app.js i have use this file as

app.use(require('./routes/corsheaders'));
Atul Agrawal
  • 1,474
  • 5
  • 22
  • 41