【问题标题】:Allow CORS REST request to a Express/Node.js application on Heroku允许对 Heroku 上的 Express/Node.js 应用程序的 CORS REST 请求
【发布时间】:2012-06-15 15:21:15
【问题描述】:

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

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

在我的快递应用程序中,我正在添加 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();
    }
};

和:

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

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

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

请求方法:OPTIONS

状态码:200 OK

请求标头

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

查询字符串参数

uri:http://localhost:5000/collections/1/documents/1

响应标头

Allow:GET
Connection:keep-alive
Content-Length:3
Content-Type:text/html; charset=utf-8
X-Powered-By:Express

这看起来是否缺少 API 应用程序发送的正确标头?

谢谢。

【问题讨论】:

  • 我在我没有编写的代码中收到此错误,但我不明白 OPTIONS 方法需要处理程序。有人可以帮我理解为什么不只处理POST 方法而不是同时处理POST OPTIONS 方法吗?
  • 如果您将使用 PATCH 而不是 PUT 来更新资源,可能还需要包含它

标签: node.js rest heroku express cors


【解决方案1】:

我已经在一个干净的 ExpressJS 应用程序上检查了你的代码,它运行良好。

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

【讨论】:

  • 之所以这样做是因为您需要在app.use(app.router); Cheers 之前定义它!
  • 在我的情况下,当 req.method == 'OPTIONS' 时,在发送回 res.send(200) 后不会调用下一个 POST。我还有什么遗漏吗?
  • 2Aldo:需要代码。可能你忘记了一些标题?如果在您的服务器正确提供预检 OPTIONS 请求后您的客户端未发送 POST,请尝试检查开发人员工具控制台。 WebKit 将此类错误记录到 Web 检查器的控制台。
  • @ConnorLeech 非常好。我一直在使用上述的 allowCrossDomain 方法,并且厌倦了处理所有这些标头管理。另外 - 因为我们只需要 CORS 来进行开发,所以花费这么多周期来弄清楚发生了什么是没有任何意义的。很高兴有 node.js 支持,可以轻松实现这一点。
  • @ConnorLeech 我认为您应该添加您的评论作为答案...就像一种享受,它既好又简单
【解决方案2】:

我将其添加为答案只是因为原始帖子是作为评论放入的,因此当我第一次浏览此页面时它确实被你忽略了。

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

还可能值得指出的是,我上面提到的原始评论是在 2014 年发表的。现在是 2019 年,查看 npm package's github page 回购协议是在 9 天前更新的。

【讨论】:

    【解决方案3】:

    要支持带有凭据的 cookie,您需要此行 xhr.withCredentials = true;

    mdn docs xhr.withCredentials

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

    【讨论】:

      【解决方案4】:

      按照以下步骤操作:

      npm install cors --save

      在你的根 js 文件中:

       var express = require('express') 
       var cors = require('cors')
       var app = express()
       app.use(cors())
      

      【讨论】:

        【解决方案5】:

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

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

        我希望这对某人有所帮助。

        【讨论】:

        • 是的,这就是我的问题。您能否更具体地说明您是如何解决问题的。我仍在开发中,并在 Express.js w/node cors 包上运行。
        • @alan 我正在使用 Promise 来验证我的应用程序中的令牌,如果未定义 JWT 机密,则 Promise 将永远无法解析,如果您需要进一步,这是我正在使用的 code参考。
        • 感谢您的回复。我将查看代码。秘密地,我假设您正在谈论第二个私钥。我正在使用 oauth2。
        • 我要补充一点,任何失败的承诺都会产生这种误导性的错误!我必须明确说明正在使用的 Node 版本,否则我的数据库调用(mongo)只是挂起,浏览器唯一能告诉我的是 503,然后是一些与 Cors 相关的愚蠢。这个错误真的让我很困惑,因为我有 app.use(cors()); 去。
        • @CatBrownie,感谢您的回答。正是我需要的!
        【解决方案6】:

        Cors 错误可能掩盖了您的实际错误。查看您的 heroku 构建日志以查看您潜在的真正错误。我的是这个。

        Heroku Postgres: "psql: FATAL: no pg_hba.conf entry for host"

        【讨论】:

          猜你喜欢
          • 2013-03-29
          • 2015-01-16
          • 2020-05-25
          • 1970-01-01
          • 1970-01-01
          • 2016-07-19
          • 2023-03-10
          • 2018-07-28
          • 1970-01-01
          相关资源
          最近更新 更多