express-http-proxy仍然受到CORS策略的阻止。

4
我有一个静态服务于我的Polymer项目的express服务器。我需要进行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>

在脚本部分,我正在ready函数中使用this.$.getBugs.generateRequest()发送请求。所以我加载这个,期望请求不会被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)而被阻止,因为它是从服务器发出的,而非客户端,这正是代理的全部意义。

4个回答

1

可能是因为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 可能会大大简化问题。但我不知道你的开发限制,所以我可能错了。


谢谢,这确实解决了任何CORS问题。不幸的是,“cors”包与“express-http-proxy”不兼容,这就是为什么需要手动设置这些标头的原因。 - Fez Vrasta
很高兴它能够正常工作@FezVrasta。关于cors包,它不是你必须插入到express-http-proxy中的东西。它是一个独立的中间件,允许你在目标服务器上接受来自经过筛选的主机列表的请求,例如app.use(cors(['http://localhost:8080', 'https://www.mywebsite.com']))。如果你的问题仅仅是你的API服务器拒绝来自前端的请求,那么它可能会更有用和简单。 - geauser
在我的情况下,我正在使用Node.js服务器代理第二个REST API,因此我不能只使用cors包。 - Fez Vrasta

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

OP 正在尝试代理第二个服务器,这就是他们使用代理软件包的原因。您的回复没有回答问题。 - Fez Vrasta

-1

服务器可能返回了一个 302 重定向,但使用的中间件没有正确处理。

了解更多关于重定向的信息:https://zh.wikipedia.org/wiki/HTTP_302

您可以修改 Location 响应头来解决 CORS 问题,或者尝试:

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

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

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

上面的示例应该自动处理重定向。


OP 询问的是 express-http-proxy,而不是 http-proxy-middleware。 - Fez Vrasta

-2

另一个解决方案是使用http-proxy-middleware,如@chimurai所述。

如果您想代理到一个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错误。


1
express-http-proxy和http-proxy-middleware是两个不同的东西。你不能用http-proxy-middleware解决express-http-proxy的问题。 - Alan Yong

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