Node.js - 我该如何转发HTTP流量(反向代理)?

4
我需要一个反向代理,但我需要在Node.js中实现它,因为我需要添加一些自定义功能。
这个“网关”将是唯一可见的服务,它需要将流量转发到内部服务网络。一个简单的302并不能解决这个问题。
考虑到Node.js的异步特性,我应该如何实现这个过程?
是否有任何众所周知的库用于此?
3个回答

3

我已经使用node-http-proxy实现了这一点,其中http://first.test/http://second.test/是主机名。

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

var proxy = httpProxy.createProxyServer({});

// reverse proxy server
http.createServer(function (req, res) {
    var target = '';

    if (req.headers.host.match(/first.test/)) {
        target = 'http://127.0.0.1:8001';
    } else if (req.headers.host.match(/second.test/)) {
        target = 'http://127.0.0.1:8002';
    }

    console.log(req.headers.host, '->', target);
    proxy.web(req, res, { target: target });
}).listen(8000);

// test server 1
http.createServer(function(req, res) {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.write('8001\n');
    res.write(JSON.stringify(req.headers, true, 2));
    res.end();
}).listen(8001);

// test server 2
http.createServer(function(req, res) {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.write('8002\n');
    res.write(JSON.stringify(req.headers, true, 2));
    res.end();
}).listen(8002);

2
对于一个使用反应器模式(如node)的简单反向代理,我建议您考虑使用nginx。但是,您提到您想使用node添加一些自定义功能,那么这是一个现实的目标吗?绝对可以!在设计反向代理时,以下是需要考虑的一些事项:
- 您将如何跟踪传入请求需要到达何处?例如,如果您将所有请求代理到/UI/test/*,但返回的HTML具有根相对URL(/imgs/banner.jpg),那么您如何跟踪随后的请求需要去哪里(特别是如果它来自javascript)?您是否要紧密耦合代理和后端应用程序?或者您可以考虑设置cookie以进行跟踪。 - 这个东西需要扩展吗?如果您的答案是否定的,我的后续问题是 - 您确定吗?如果您确实只需要代理到两个后端应用程序,我相信有许多聪明的方法可以实现。如果您随时可能有N个后端应用程序,则需要一个管理(添加/删除/更新)它们的可靠计划。 - 您的应用程序是否使用HTTPS?如果是,您是否要在代理上终止SSL?您能否在代理和后端应用程序之间发送明文数据?
祝您的反向代理工作顺利!如果我想到其他内容,我会更新此内容。

一些非常好的观点。所有路由都将基于主机名而不是路径。虽然会涉及到扩展,但这是另一个问题。SSL也将被使用,但同样,这是设计的另一个部分的问题。你提出了一些很好的观点,我感谢你对它们进行了深入思考! - Adam K Dean

1

使用纯核心模块(可能有点丑陋,但高效):

var http = require('http');

http.createServer(function (request, response) {
    if (request.headers.host === 'api.test') {
        // request data from 172.17.0.1:80
    } else if (request.headers.host === 'test') {
        // request data from 172.17.0.2:80
    } else {
        // Do something else
    }
}).listen(80);

如果您不喜欢这个例子,可以尝试:https://www.npmjs.org/package/turtle.io

谢谢,我之前没听说过 turtle.io。不过我用 node-http-proxy 成功实现了这个功能(代码如下)。还是非常感谢你的回复,我们的思路是一致的,只是我加入了 proxyServer 就可以了。感谢你的建议! - Adam K Dean
一个查找表对于这个问题会更好:{ "api.test" : function() { ... }, ...} 可以用作一个简单的分发表。 - tadman

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