使用Node.js将远程服务器上的http请求重定向到本地服务器。

5

在Charles这个工具中有一个功能,可以让你映射远程请求:

http://www.charlesproxy.com/documentation/tools/map-remote/

基本上,它可以接收任何针对服务器的请求(即使你不是运行它的人),然后向另一个服务器发出新的请求,保留路径和查询字符串。第二个服务器的响应将覆盖第一个服务器的响应。

我只想知道是否有一个Node模块可以做到这一点。我尝试使用http-proxy,但我觉得这个映射远程工具与代理有点不同,因为似乎你必须拥有两个服务器才能使用代理。

编辑:再次尝试使用http-proxy Node模块,但似乎无法正常工作。以下是我的代码:

var http = require('http')
, httpProxy = require('http-proxy');

httpProxy.createServer({
    hostnameOnly: true,
    router: {
        'www.stackoverflow.com': 'localhost:9000',
    }
}).listen(80);

// Create your target server
//
http.createServer(function (req, res) {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2));
  res.end();
}).listen(9000);

我的期望是,当我访问www.stackoverflow.com或www.stackoverflow.com:80时,它会重定向到我的localhost:9000

4个回答

4
不,你所要求的确实是一个简单的代理。而且,你不必拥有两个服务器才能运行代理。你只需要代理请求,然后在那一点上,你可以随心所欲地修改数据。
你提到的代理模块可以正常工作,还有许多其他模块。如果你希望的话,也可以使用简单的Nginx配置来完成这个任务。

我进行了更多的研究,这不仅仅是一个简单的代理,而是一个反向代理吗? - prashn64
4
不是,只是一个代理服务器。事实上,“反向代理”这个术语几乎没有意义。通常,当您在服务器旁边放置代理服务器以进行负载均衡(等等)时,才会使用该术语。然而,它仅仅就是一个代理服务器。你已经为你的问题添加了更多信息……你是否设置了一个hosts文件条目,将www.stackoverflow.com指向你的Node.js服务器的IP地址? - Brad
如果可能的话,我宁愿不更改配置。路由表不应该自动处理这个吗? - prashn64
啊,好的,这很有道理。实际上,我完全不知道 Charles 是如何工作的,对我来说它现在是一个黑匣子。所以听起来唯一能让这个在任何计算机上只需一个单节点服务器命令就能工作的选项是设置正确配置的 DNS 服务器?你知道我是否需要另一个节点模块来处理这个吗? - prashn64
1
@prashn64 Charles只是一个代理服务器。当你运行它时,它会将自己设置为系统代理服务器。如果你想让其他机器使用你的代理服务器,你必须对它们进行配置。如果你想让你的机器在某些地址上使用备用服务器而不使用代理,你必须重新配置它们使用的任何DNS服务器。这与你的应用程序无关...它取决于DNS服务器。目前我完全不清楚你想做什么。 - Brad

3
我用我的解决方案制作了这个pastebin: http://pastebin.com/TfG67j1x 将pastebin的内容保存为proxy.js。确保在与proxy.js文件相同的文件夹中安装依赖项(npm install http-proxy colors connect util --save)。
当您运行代理时,它会:
- 启动一个新的服务器,监听8013端口,充当代理服务器; - 启动一个演示目标服务器,监听9013端口。
通过代理访问演示目标时,它会将“Ruby”字符串修改为“nodejitsu”,以便进行简单的测试。如果您在公司防火墙/代理后面,则此脚本暂时无法使用。
更新: “headers already sent”问题发生在第32/33行。事实证明,同一连接上发生了多个错误。当第一个错误发生时,头文件将被发送,当第二个错误发生时,头文件已经发送;因此会引发“headers already sent”异常并终止服务器。
通过此修复,服务器不再崩溃,但它仍然无法解决错误的源头,即NODE.JS无法访问您的目标站点。您必须处于另一个代理/防火墙后,并且NodeJS需要将HTTP请求转发到第二个代理。如果您通常使用浏览器代理连接到Internet,则我的解决方案将失败。尽管如此,您没有指定这是一个要求。
您可以通过代理访问您网络内部的服务器(通常不需要代理)来验证这一点。
更新2:您不应直接尝试访问http://localhost:8013,而应将其设置为浏览器中的代理。注意您原始的浏览器代理设置(请参见上文)。然后尝试访问http://localhost:9013。

1
我遇到了这个错误:`http.js:645 throw new Error('Can\'t set headers after they are sent.');`这是因为防火墙问题吗? - prashn64
顺便说一下,那是我尝试连接到本地主机:8013时出现的。 - prashn64
我尝试了您的更新,确实不再出现那些错误。然而,我仍然没有看到更改后的“Ruby”->“nodejitsu”文本变化。此外,当我访问stackoverflow.com时,我没有被重定向到localhost:9013。我检查了我的浏览器代理,但似乎没有设置任何内容。 - prashn64
代理服务器在设置为您的浏览器和您正在访问的服务器之间的中间人时起作用。在访问stackoverflow.com之前,您必须设置您的浏览器使用代理服务器localhost:8013,否则您将看到正常的浏览器行为。 您似乎混淆了代理服务器的工作方式和HTTP URL重定向的工作方式(https://dev59.com/QW035IYBdhLWcg3wc_sm)。设置代理后,浏览器将表现得好像内容确实直接来自Web服务器,重定向在GUI中不可见(即地址中的URL不会更改)。 - BogdanBiv
好久不见了...我仍然不知道我的回答是否真正帮助了你。 - BogdanBiv
我还需要检查一下将浏览器设置为使用代理服务器是否有效。周末会有时间去检查它。 - prashn64

1

你是否将代理添加到浏览器配置中?否则,底层操作系统会直接将你的请求路由到 www.stackoverflow.com,此时代理无法捕获。


1

您能确认一下 www.stackoverflow.com 是否最终指向了您的 node.app 吗?目前该名称将解析为导致您访问此网站的IP地址,因此您必须确保该名称现在解析为您的 node.app。在这种情况下,这可能意味着编辑您的 hosts 文件。


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