允许对 Heroku 上的 Express/Node.js 应用程序的 CORS REST 请求

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11001817/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 15:52:07  来源:igfitidea点击:

Allow CORS REST request to a Express/Node.js application on Heroku

node.jsrestherokuexpresscors

提问by Jamie Folsom

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

我已经在 node.js 的 express 框架上编写了一个 REST API,它适用于来自 Chrome 中的 js 控制台和 URL 栏等的请求。我现在正试图让它适用于来自另一个应用程序的请求,在不同的域 (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.

javascript 前端自动发出的第一个请求是/api/search?uri=,并且似乎在“预检”OPTIONS 请求中失败。

In my express app, I am adding CORS headers, using:

在我的快递应用程序中,我正在添加 CORS 标头,使用:

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:

从 Chrome 控制台我得到这些标题:

Request URL:http://furious-night-5419.herokuapp.com/api/search?uri=http%3A%2F%2Flocalhost%3A5000%2Fcollections%2F1%2Fdocuments%2F1

请求地址:http://furious-night-5419.herokuapp.com/api/search?uri=http%3A%2F%2Flocalhost%3A5000%2Fcollections%2F1%2Fdocuments%2F1

Request Method:OPTIONS

请求方式:OPTIONS

Status Code:200 OK

状态码: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?

这看起来是不是 API 应用程序发送的头文件不正确?

Thanks.

谢谢。

采纳答案by Olegas

I've cheked your code on a clean ExpressJS app and it works just fine.

我在一个干净的 ExpressJS 应用程序上检查了你的代码,它工作得很好。

Try move your app.use(allowCrossDomain)to the top of configure function.

尝试将您app.use(allowCrossDomain)的移动到配置功能的顶部。

回答by doron aviguy

for supporting cookies withCredentials you need this line xhr.withCredentials = true;

为了支持 cookie withCredentials 你需要这一行 xhr.withCredentials = true;

mdn docs xhr.withCredentials

mdn 文档 xhr.withCredentials

In the Express Server add this block before all the other

在 Express Server 中,将此块添加到所有其他块之前

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

回答by flyingace

I'm adding this as an answeronly 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.

正如@ConnorLeech 在他对上述已接受答案的评论中指出的那样,有一个非常方便的 npm 包,毫不奇怪,名为 cors。它的使用非常简单var cors = require('cors'); app.use(cors());(同样,来自 Leech 先生的回答),也可以以更严格、更可配置的方式应用,如他们的文档中所述

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 pagethe repo was updated as recently as nine days ago.

可能还值得指出的是,我上面提到的原始评论是在 2014 年发表的。现在是 2019 年,查看npm 包的 github 页面,该存储库最近在 9 天前更新。

回答by CatBrownie

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.

对于大多数浏览此问题的人来说,情况并非如此,但我遇到了完全相同的问题,并且解决方案与CORS.

Turns out that JSON Web Token secret stringwas not defined in the environment variables, so the token could not be signed. This caused to any POSTrequest that relies on checking or signing a token to get a timeout and return a 503error, telling the browser that there's something wrong in CORS, which it's not. Adding the environment variable in Heroku solved the issue.

事实证明 JSON Web Token 秘密string未在环境变量中定义,因此无法对令牌进行签名。这导致任何POST依赖于检查或签署令牌以获得超时并返回503错误的请求,告诉浏览器在 中存在问题CORS,但事实并非如此。在 Heroku 中添加环境变量解决了这个问题。

I hope this helps someone.

我希望这可以帮助别人。