express-http-proxy仍然被CORS策略阻止

时间:2017-02-16 17:48:05

标签: javascript ajax node.js proxy polymer

我有一台静态服务器静态服务我的Polymer项目。我有一个REST API查询,我需要做,但如果我从客户端进行,它将被CORS阻止。所以我用express-http-proxy试图解决这个问题;我将请求发送给它,它重定向到具有REST API端点的服务器。这是与node server.js一起运行的整个服务器代码:

var express = require('express');
var proxy = require('express-http-proxy');

var server = express();
server.use('/', express.static(__dirname + '/'));
server.listen(8080);
server.use('/rest/api/2/search', proxy('restserver:8877'));
console.log("Server listening on localhost:8080");

当我在浏览器中访问restserver:8877 / rest / api / 2 / search时,会返回一堆json作为“默认”搜索。

在客户端,我有iron-ajax发出此请求:

<iron-ajax
            id="getBugs"
            url="/rest/api/2/search"
            params=''
            on-response="handleResponse"
            debounce-duration="300">
        </iron-ajax>

在脚本部分,我在this.$.getBugs.generateRequest()函数中使用ready来发送请求。所以我加载它,期望请求不被CORS阻止,因为......它正由服务器代理。相反,Chrome devtools给了我这个:

XMLHttpRequest cannot load http://restserver:8877/secure/MyJiraHome.jspa. Redirect from 'http://restserver:8877/secure/MyJiraHome.jspa' to 'http://restserver:8877/secure/Dashboard.jspa' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.

我不明白为什么它会给我这些URL,因为我从来没有引用它们,以及为什么它因CORS而阻塞,因为它来自服务器而不是客户端,这是代理的全部要点。 / p>

4 个答案:

答案 0 :(得分:0)

服务器可能正在返回302重定向,但在使用的中间件中未正确处理。

详细了解重定向的工作原理:https://en.wikipedia.org/wiki/HTTP_location

您可以修改Location响应标头以克服CORS问题,或者您可以尝试:

var proxy = require('http-proxy-middleware');

var restServerProxy = proxy({target: 'http://restserver:8877', autoRewrite: true});

server.use('/rest/api/2/search', restServerProxy);

以上示例应自动处理重定向。

答案 1 :(得分:0)

替代解决方案是使用@chimurai提到的 http-proxy-middleware

如果您想代理 https 服务器以避免CORS:

const proxy = require('http-proxy-middleware');

app.use('/proxy', proxy({
    pathRewrite: {
       '^/proxy/': '/'
    },
    target: 'https://server.com',
    secure: false
}));

此处需要设置 secure:false 以避免 UNABLE_TO_VERIFY_LEAF_SIGNATURE 错误。

答案 2 :(得分:0)

可能是 express-http-proxy 只是转发来自客户端的 Origin 标头,即 http://localhost:8080,导致终端服务器拒绝它。

尝试用 proxyReqOptDecorator 修改它:

server.use('/rest/api/2/search', proxy('restserver:8877', {
  proxyReqOptDecorator(proxyReqOpts) {
    proxyReqOpts.headers['Origin'] = 'http://accepted.origin.com';
    return proxyReqOpts;
  }
}));

从未使用过 express-http-proxy 并且没有对其进行测试,所以如果这不是解决方案,请告诉我。另外我认为按照其他人的建议使用 cors 可以简化很多事情。但我不知道你的发展限制,所以我可能是错的。

答案 3 :(得分:-1)

您不需要任何代理。由于您在服务器上调用端点,因此您可以将客户端列入白名单以调用您的服务器。您可以使用 cors 包来做到这一点。

https://www.npmjs.com/package/cors

首先,在一个文件中定义您的 CORS 策略逻辑(让我们将其命名为 cors-policy-logic.js),然后将其导出以便您可以在其他文件中使用它。

const cors = require('cors');

const whitelist = ['http://localhost:8080', 'http://localhost:your_client_url'];

var corsOptionsDelegate = (req, callback) => {
  var corsOptions;
  if (whitelist.indexOf(req.header('Origin')) !== -1) {
    corsOptions = { origin: true };
  } else {
    corsOptions = { origin: false };
  }
  callback(null, corsOptions);
};

exports.cors = cors();
exports.corsWithOptions = cors(corsOptionsDelegate);

现在,导入它并在您定义端点的任何地方使用它:

var express = require('express');
const cors = require('./cors-policy-logic.js');

var server = express();
server.use('/', express.static(__dirname + '/'));
server.listen(8080);

server.route('/rest/api/2/search')
  .options(cors.corsWithOptions, (req, res) => { res.sendStatus(200); })
  .get(cors.cors, (req, res, next) => {
     //Your business logic
  });

console.log("Server listening on localhost:8080");