Nodejs express, Heroku CORS

16
我的应用程序的服务器端使用Node和express构建,
在本地运行良好,但现在我已经上传到Heroku,
即使我在应用程序中处理了它,我仍然遇到CORS错误。
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
        })
      }
    })
})

在我的HTTP请求中

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

  }

}

还有来自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

浏览器中的错误。
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.

这是我从Heroku收到的错误信息,与我请求的路径有关。
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

你的应用程序似乎在 OPTIONS 请求(这是 CORS 预检请求)上崩溃了,这很奇怪,因为我认为预检请求不会针对 GET 请求发出。 - robertklep
@robertklep 也许Heroku正在添加额外的保护层?我会去检查一下。 - eko
@echonax 嗯,这取决于浏览器是否应该发出预检请求。我无法想象Heroku会自行发出这样的请求。 - robertklep
4个回答

20

尝试同时允许凭据:

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

编辑:

如果你想在你的Heroku应用中进行本地HTTP调用,可以更改:

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

他们似乎正在测试CORS是否有效,通过请求跨域(源是http://localhost:4200)。 - robertklep
@robertklep 噢,你的意思是OP试图从本地应用程序向部署在Heroku上的应用程序发出请求? - eko
1
是的,对我来说就是这样的 :D - robertklep
是的,没错,我正在尝试从本地主机访问它,我已经添加了凭据部分,但仍然没有反应,同时也更新了问题。 - RasMason
@Roy 如果该代码库已部署在Github上,您能分享链接吗? - eko
显示剩余4条评论

7
另一个可能的原因是缺少.env变量。在部署Heroku服务器时,所有.env变量必须通过Heroku的config vars设置。
如果路由需要缺失的.env,出于某种原因它会返回CORS错误。
在我的情况下,jsonwebtoken正在寻找process.env.secretkey,所以调用jsonwebtoken的所有路由都返回CORS错误,而不需要它的路由可以正常工作。

5

问题已经解决,原因是Heroku只安装您的依赖项中的软件包,而我需要的软件包在devDependencies中,所以一旦我将其重新安装为依赖项,它就可以工作了!


3

我遇到了同样的问题,在Heroku上遇到了cors错误。原因是我的服务器在Heroku上产生了一些错误。检查了Heroku中的应用程序日志,发现生产环境变量未定义的错误。因此,我定义了我的环境变量,bingo!再也没有cors错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接