如何编网站的HTTP反向代理服务器

发布时间:2022-05-14 12:04:58 作者: 来源: 浏览量(1633 )
摘要:为了简化从 Readable Stream 监听 data 事件来获取数据并使用 Writable Stream 的 write() 方法来输出,可以使用 Readable Stream 的 pipe() 方法。那么如何编写 HTTP 反向代理服务器? 简单版本 以下是实现一个简单...

 为了简化从 Readable Stream 监听 data 事件来获取数据并使用 Writable Stream 的 write() 方法来输出,可以使用 Readable Stream 的 pipe() 方法。那么如何编写 HTTP 反向代理服务器?

简单版本

以下是实现一个简单 HTTP 反向代理服务器的各个文件和代码(没有任何第三方库依赖), 为了使代码更简洁,使用了一些最新的 ES 语法特性,需要使用 Node v8.x 最新版本来运行 :

文件 proxy.js :

const http = require("http");

const assert = require("assert");

const log = require("./log");

/** 反向代理中间件 */

module.exports = function reverseProxy(options) {

assert(Array.isArray(options.servers), "options.servers 必须是数组");

assert(options.servers.length > 0, "options.servers 的长度必须大于 0");

// 解析服务器地址,生成 hostname 和 port

const servers = options.servers.map(str => {

const s = str.split(":");

return { hostname: s[0], port: s[1] || "80" };

});

// 获取一个后端服务器,顺序循环

let ti = 0;

function getTarget() {

const t = servers[ti];

ti++;

if (ti >= servers.length) {

ti = 0;

}

return t;

}

// 生成监听 error 事件函数,出错时响应 500

function bindError(req, res, id) {

return function(err) {

const msg = String(err.stack || err);

log("[%s] 发生错误: %s", id, msg);

if (!res.headersSent) {

res.writeHead(500, { "content-type": "text/plain" });

}

res.end(msg);

};

}

return function proxy(req, res) {

// 生成代理请求信息

const target = getTarget();

const info = {

...target,

method: req.method,

path: req.url,

headers: req.headers

};

const id = `${req.method} ${req.url} => ${target.hostname}:${target.port}`;

log("[%s] 代理请求", id);

// 发送代理请求

const req2 = http.request(info, res2 => {

res2.on("error", bindError(req, res, id));

log("[%s] 响应: %s", id, res2.statusCode);

res.writeHead(res2.statusCode, res2.headers);

res2.pipe(res);

});

req.pipe(req2);

req2.on("error", bindError(req, res, id));

};

};

文件 log.js :

const util = require("util");

/** 打印日志 */

module.exports = function log(...args) {

const time = new Date().toLocaleString();

console.log(time, util.format(...args));

};

说明:

log.js 文件实现了一个用于打印日志的函数 log() ,它可以支持 console.log() 一样的用法,并且自动在输出前面加上当前的日期和时间,方便我们浏览日志

reverseProxy() 函数入口使用 assert 模块来进行基本的参数检查,如果参数格式不符合要求即抛出异常,保证可以第一时间让开发者知道,而不是在运行期间发生各种不可预测的错误。

getTarget() 函数用于循环返回一个目标服务器地址

bindError() 函数用于监听 error 事件,避免整个程序因为没有捕捉网络异常而崩溃,同时可以统一返回出错信息给客户端。

以上就是小编对于编写 HTTP 反向代理服务器的建议。

扫一扫二维码,直接手机访问此页

扫码访问手机页面

【免责声明】本网站的部分文章信息(文字、图片、音频视频文件等资源)来自于网络,均是为公众传播有益咨询信息之目的,其版权归版权所有人所有。 本站采用的非本站原创文章及图片等内容无法一一与版权者联系,如果本站所选内容的文章作者及编辑认为其作品不宜供大家浏览,或不应无偿使用, 请及时联系我们删除,同时向您深表歉意!请发送邮件153462496@qq.com进行联系。

感兴趣吗?

欢迎联系我们,我们愿意为您解答任何有关网站疑难问题!

在线客服
嘿,我来帮您!