1

我有这样的节点反向代理设置:

var options = {
  pathnameOnly: true,
  router: {
    '/myapp': '127.0.0.1:9000',
  }
}
httpProxy.createServer(options).listen(8000);

位于9000根目录的webapp有一个index.html文件,其中包含如下样式表链接:

<link rel="stylesheet" href="styles/blue.css">

当我直接点击localhost:9000时,会加载 html 并找到 css。然后我通过localhost:8000/myapp的反向代理点击它,但是我得到一个错误 404因为localhost:9000/styles/blue.css is not found,因为文件显然是在localhost:9000/myapp/styles/蓝色.css

我的应用程序的 html 当然不知道反向代理,所以我无法在 index.html 中解决这个问题。所以我想我错过了一些关于代理设置的基本信息?

4

1 回答 1

1

我不知道您现在是否找到了解决方法,但是我遇到了完全相同的问题,并且认为我已经解决了。

当您直接点击目标端点时localhost:9000,路径将通过 as 发送/,即只是根。然后,当它请求 css 等时,它会从根目录按预期解决这些问题。

当您通过代理调用时,localhost:8000/myapp它会路由/myapp到目标,然后将目标服务/作为路径传递,此时它的行为与上述完全相同。

这里的问题实际上出在浏览器上。因为路径被指定为/myapp,所以它假定“myapp”是一个文件名。然后,当它请求 css 等时,它会将其剥离回最后一个斜杠并将其用作所有相对 href 的基础,这就是为什么它会要求/styles/blue.css而不是/myapp/styles/blue.css. 如果您尝试浏览localhost:8000/myapp/- 请注意尾部斜杠 - 那么它可以工作,因为浏览器现在将/myapp/其视为路径的一个组成部分。

显然,您不能规定用户必须添加尾部斜杠。而且你不能轻易地在目标服务中做很多事情,如果只是因为它没有看到任何区别,而且无论如何你不想在每个终端服务中重复相同的解决方案。所以答案似乎是在代理中拦截它。

此示例有效,尽管可能有更强大的实现方式。它寻找路径的最后一部分可能是目录组件的情况,在这种情况下,请求被重定向以强制浏览器重新发出带有斜杠的请求。它会根据它看起来不像filename.ext或已经有斜杠来做出这个决定:

httpProxy.createServer(function(req, res, proxy) {
    var parsed = url.parse(req.url);
    if(!parsed.pathname.match(/(\w+\.\w+|\/)$/)) {
        parsed.protocol = 'http';
        parsed.host = req.headers.host;
        parsed.pathname += '/';
        res.writeHead(301, {Location: url.format(parsed)});
        res.end();
    } else {
        proxy.proxyRequest(req, res);
    }
}, options);
于 2013-12-05T23:18:08.753 回答