16

The server side of my app was built using Node with express,

It was working fine locally, but now I've uploaded to Heroku

I'm getting CORS errors, even though I've handled it within the app

index.js

var express = require('express');
var bodyParser = require('body-parser');

var http = require('http');
var path = require('path');
var twit = require('twitter');
var app = express();
var port = process.env.PORT || 3000;

var twitter = new twit({
  consumer_key:  'myKey',
  consumer_secret: 'mySecret',
  access_token_key: 'myKey',
  access_token_secret: 'mySecret'
});
app.set('port', (port));
var server = http.createServer(app).listen(port, function() {
  console.log('Server listening on port ' + port);
});
app.use(bodyParser.urlencoded({extended: true}));

app.use(function (req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
    res.setHeader('Access-Control-Allow-Methods', 'POST, GET, PATCH, DELETE, OPTIONS');
    next();
});

app.get('/gettweets', function (req, res) {
  twitter.get('statuses/user_timeline', { id: 23445555, count: 3 }, function(err, tweets, response) {
      if (!err) {
         res.json(tweets);
      }
      else {
        return res.status(500).json({
          title: 'An error has occured',
          error: err
        })
      }
    })
})

And in my http call

export class SocialService {

  private url = 'https://myserver.herokuapp.com/';
  constructor(private http: Http) { }

  initialise(){
    var headers = new Headers();
        headers.append('Content-Type', 'application/json');

    return this.http.get(this.url+'gettweets', {headers: headers})
        .map((response: Response) => {
        console.log(response.json());
          return response.json();
        })
        .catch((error: Response) =>  Observable.throw(error.json()) )

  }

}

And the build log from Heroku

-----> Node.js app detected
-----> Creating runtime environment

       NPM_CONFIG_LOGLEVEL=error
       NPM_CONFIG_PRODUCTION=true
       NODE_VERBOSE=false
       NODE_ENV=production
       NODE_MODULES_CACHE=true
-----> Installing binaries
       engines.node (package.json):  unspecified
       engines.npm (package.json):   unspecified (use default)

       Resolving node version 6.x via semver.io...
       Downloading and installing node 6.10.3...
       Using default npm version: 3.10.10
-----> Restoring cache
       Loading 2 from cacheDirectories (default):
       - node_modules
       - bower_components (not cached - skipping)
-----> Building dependencies
       Installing node modules (package.json)
-----> Caching build
       Clearing previous node cache
       Saving 2 cacheDirectories (default):
       - node_modules
       - bower_components (nothing to cache)
-----> Build succeeded!
-----> Discovering process types
       Procfile declares types     -> (none)
       Default types for buildpack -> web
-----> Compressing...
       Done: 17.8M
-----> Launching...
       Released v5
       https://myserver.herokuapp.com/ deployed to Heroku

And error in Browser

XMLHttpRequest cannot load https://myserver.herokuapp.com/gettweets.
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 503.

This is the error I'm getting from Heroku, something to do with the path I'm requesting

2017-05-11T12:54:05.960151+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=OPTIONS path="/gettweets" host=maleonserver.herokuapp.com request_id=5c052790-67df-4677-be8b-14cc2bc71292 fwd="5.67.244.130" dyno= connect= service= status=503 bytes= protocol=https
RasMason
  • 1,968
  • 4
  • 32
  • 54
  • Your app seems to be crashing on an `OPTIONS` request (which is a CORS preflight), which is strange, because I don't think preflight requests are issued for `GET` requests. – robertklep May 11 '17 at 13:11
  • @robertklep Might heroku be adding that extra layer of protection? Gonna check that – eko May 11 '17 at 13:24
  • @echonax well, it's the browser that determines if a preflight request should be issued. I can't imagine that Heroku would issue such a request itself. – robertklep May 11 '17 at 13:26

4 Answers4

20

Try to also allow the credentials:

app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", '*');
    res.header("Access-Control-Allow-Credentials", true);
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header("Access-Control-Allow-Headers", 'Origin,X-Requested-With,Content-Type,Accept,content-type,application/json');
    next();
});

Edit:

Also if you want to make a local http call in your heroku app; change

private url = 'https://myserver.herokuapp.com/';

to

private url = '/';
eko
  • 39,722
  • 10
  • 72
  • 98
  • They seem to be testing to see if CORS works by requesting cross-domain (the origin is `http://localhost:4200`). – robertklep May 11 '17 at 12:47
  • @robertklep oh you mean OP is trying to make a request from the local app to the one deployed on heroku? – eko May 11 '17 at 12:49
  • 1
    Yes, that's what it looks like to me :D – robertklep May 11 '17 at 12:50
  • Yes that's right I'm trying to access it from local host, I added the credentials part but still nothing, also updated question – RasMason May 11 '17 at 13:03
  • @Roy Just curious to know, The solution provided here worked for you? – David R May 11 '17 at 13:28
  • @Roy if the repo is deployed on github can you share the link? – eko May 11 '17 at 13:29
  • @echonax Thanks, https://github.com/royadams72/maleon I'm only uploading what's in the server folder – RasMason May 11 '17 at 13:57
  • did u know i got cors error but the data has been on inserted on database ? in frontend error but when refresh , the data has inserted . i deploy 2 apps with outside database server . apixxx.heroku.com forntendxxx.heroku.com – Yogi Arif Widodo Aug 10 '22 at 01:58
  • ah solved thanks its helpfull , before i only solve in other server just only with cors package . ```var corsOptions = { origin: "*", optionsSuccessStatus: 200, }; app.use(cors(corsOptions));``` but its not work on heroku, now its work with your technique! nice! – Yogi Arif Widodo Aug 10 '22 at 02:05
6

It worked out, the issue was caused by Heroku only installing packages from your dependencies and what I needed was in the devDependencies, so once I reinstalled as dependencies it worked!

Ivan Bila
  • 747
  • 7
  • 9
RasMason
  • 1,968
  • 4
  • 32
  • 54
6

another possible cause is missing .env variables. When deploying a heroku server, all .env variables have to be set via heroku's config vars.

If the route required a missing .env, for some reason it returns as a CORS error.

In my case, the jsonwebtoken was looking for process.env.secretkey, so all routes that called for the jsonwebtoken returned with CORS error, while routes that does not require it worked just fine.

Stefani
  • 142
  • 1
  • 2
  • 10
3

I was having the same issue. I was getting cors error on Heroku. The reason was that my server was producing some errors on Heroku. Checked my application log on Heroku found out that there was an error of production env variable not defined. So I defined my env variable and bingo! there was no further cors error.