简体   繁体   English

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

[英]express-http-proxy still gets blocked by CORS policy

I have an express server statically serving my Polymer project.我有一个静态服务于我的 Polymer 项目的快速服务器。 I have a REST API query that I need to make, but if I make it from the client it will be blocked by CORS.我有一个需要进行的 REST API 查询,但如果我从客户端进行查询,它将被 CORS 阻止。 So I used express-http-proxy to try to get around that;所以我使用express-http-proxy来尝试解决这个问题; I send my request to it, and it redirects to the server that has the REST API endpoint on it.我向它发送我的请求,它重定向到上面有 REST API 端点的服务器。 This is the entirety of my server code that's running with node server.js :这是与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");

When I access restserver:8877/rest/api/2/search in a browser it returns a bunch of json as a 'default' search.当我在浏览器中访问 restserver:8877/rest/api/2/search 时,它会返回一堆 json 作为“默认”搜索。

On the client side, I have iron-ajax making this request:在客户端,我有 iron-ajax 提出这个请求:

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

And in the script section, I'm using this.$.getBugs.generateRequest() in the ready function to send the request.在脚本部分,我在ready函数中使用this.$.getBugs.generateRequest()来发送请求。 So I load this up, expecting the request to not be blocked by CORS, since... it's being proxied by the server.所以我加载它,希望请求不会被 CORS 阻止,因为......它正在被服务器代理。 Instead, Chrome devtools gives me this:相反,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.

I don't understand why it's giving me those URLs, since I never reference them, and why it's blocking due to CORS, since it's going from the server, not the client, that being the whole point of the proxy.我不明白为什么它给我这些 URL,因为我从不引用它们,以及为什么它会由于 CORS 而阻塞,因为它来自服务器,而不是客户端,这是代理的全部意义所在。

It may be that express-http-proxy simply forwards the Origin header coming from your client which is http://localhost:8080 , causing the end server to reject it.可能是express-http-proxy只是转发来自您的客户端的Origin标头http://localhost:8080 ,导致终端服务器拒绝它。

Try modifying it with proxyReqOptDecorator :尝试使用proxyReqOptDecorator修改它:

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

Never used express-http-proxy and did not test it tho, so tell me if it's not a solution.从未使用过express-http-proxy也没有对其进行测试,所以如果这不是解决方案请告诉我。 Also I think using cors as other people suggested may simplify things a lot.另外我认为像其他人建议的那样使用cors可能会简化很多事情。 But I don't know your development constraints, so I could be wrong.但我不知道你的发展限制,所以我可能是错的。

Server is probably returning a 302 redirect which is not handled correctly in the used middleware.服务器可能返回302重定向,它在使用的中间件中未正确处理。

Read more how the redirect works: https://en.wikipedia.org/wiki/HTTP_location了解更多重定向的工作原理: https ://en.wikipedia.org/wiki/HTTP_location

You can modify the Location response header to overcome the CORS issue or you can try:您可以修改Location响应标头来克服 CORS 问题,或者您可以尝试:

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

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

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

The above example should handle redirects automatically.上面的例子应该自动处理重定向。

You don't need any proxy.您不需要任何代理。 Since you are calling endpoint on your server, you can just whitelist your client side for calling your server.由于您正在调用服务器上的端点,因此您只需将客户端列入白名单即可调用您的服务器。 You can do that with cors package.你可以用cors包做到这一点。

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

First, define your CORS policy logic in one file (let's name it cors-policy-logic.js ), and then export it so you can use it in other files.首先,在一个文件中定义您的 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);

Now, import it and use it anywhere were you define some endpoint:现在,导入它并在您定义某个端点的任何地方使用它:

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

Alternative solution would be to use http-proxy-middleware as mentioned by @chimurai.替代解决方案是使用 @chimurai 提到的http-proxy-middleware

If you want to proxy to an https server to avoid CORS:如果你想代理到https服务器以避免 CORS:

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

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

Here secure: false needs to be set to avoid UNABLE_TO_VERIFY_LEAF_SIGNATURE error.这里secure: false需要设置以避免UNABLE_TO_VERIFY_LEAF_SIGNATURE错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM