节点反向代理基本路由问题

时间:2013-08-21 12:11:02

标签: node.js reverse-proxy nodejitsu

我有 node-reverse-proxy 设置如下:

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

9000 根目录下的 webapp 有一个 index.html 文件,其中包含 stylesheet 这样的链接:

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

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

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

1 个答案:

答案 0 :(得分:1)

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

当您直接点击目标端点localhost:9000时,路径将作为/发送,即仅发送到根目录。然后,当它请求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);