愿你坚持不懈,努力进步,进阶成自己理想的人

—— 2017.09, 写给3年后的自己

httpProxy模块学习记录

node-http-proxy是一个支持websocket的HTTP可编程代理库,适用于实现反向代理负载平衡一类的组件。

一、安装

使用npm安装如下:

npm install http-proxy


二、核心概念

使用http-proxy模块,首先要调用createProxyServer来创建新的代理实例,通过传入options对象,指定配置信息。如下:

const httpProxy = require('http-proxy')
const proxy = httpProxy.createProxyServer(options)

注意:除非在proxy实例上调用listen()方法,否则不会创建WEB服务器。
proxy实例中,它拥有如下方法:

  • proxy.web(req, res, [options]) 用来代理常规的HTTP(S)请求
  • proxy.ws(req, socket, head, [options]) 用来代理WS(S)请求
  • proxy.listen(port) 为了方便使用,将对象封装在一个WEB服务器内
  • proxy.close(callback) 关闭内部WEB服务器,并且停止监听给定端口

当需要调用以上的方法来代理请求时,可以这么做:

http.createServer((req, res) => {
    proxy.web(req, res, {
        target: 'http://mytarget.com:8080'
    })
})

当发生错误时,处理方式有如下两种:事件监听回调,如:

// 方法一
proxy.on('error', (e) => {
    // ...
})
// 方法二
proxy.web(req, res, options, e => {
    // ...
})

当一个请求被代理时,它拥有两个不同的管道,并转化到reqres对象里。第一个管道(传入)负责创建和操作连接客户端到目标服务器的流。而第二个管道(流出)则负责创建和操作从目标服务器响应返回给客户端的流。即:req是client->target,而res是target->client


三、使用实例

1、创建单机代理服务器

const http = require('http')
const httpProxy = require('http-proxy')
httpProxy.createProxyServer({
    target: 'http://mytarget.com:9000'
}).listen(8000)

这样当访问127.0.0.1:8000时,请求就会被代理发送给http://mytarget.com:9000,并且获得来自目标服务器的响应信息

2、创建具有自定义服务器逻辑的单机代理服务器

以下实例展示了如何使用自己的HTTP服务器来创建代理,并且对请求做一些处理:

const http = require('http')
const httpProxy = require('http-proxy')
const proxy = httpProxy.createProxyServer()
const server = http.createServer((req, res) => {
    // 这里就可以对请求做一些处理
    proxy.web(req, res, {
        target: 'http://mytarget.com:5060'
    })
})
server.listen(5050)

3、创建重写代理请求头部的单机代理服务器

const http = require('http')
const httpProxy = require('http-proxy')
const proxy = httpProxy.createProxyServer()
// 要在数据发送前修改代理连接,我们可以监听`proxyReq`事件,
// 在事件绑定后,可以接收到如下参数:
// http.ClientRequest proxyReq
// http.IncomingMessage req
// http.ServerResoinse res
// options
// 当我们需要在代理请求发送给目标服务器之前修改请求,这种机制就很有用
proxy.on('proxyReq', (proxyReq, req, res, options) => {
    proxyReq.setHeader('X-Special-Proxy-Header', 'foobar')
})
const server = http.createServer((req, res) => {
    proxy.web(req, res, {
        target: 'http://mytarget.com:5060'
    })
})
server.listen(5050)

4、对代理服务器的响应做修改

有时,当我们从原始服务器收到HTML/XML文档时,我们想在转发之前对它进行一些修改。那么,可以使用Harmon这个模块,它能够以流式传输的方式进行此操作,从而降低代理服务器的压力到最低。

5、创建带延迟的代理服务器

创建带延迟的代理服务器,只需要在http.createServer()里,用setTimeoutproxy.web()操作进行包裹即可

6、使用HTTPS

若是创建HTTPS->HTTP的反向代理,可以这么写:

httpProxy.createServer({
    target: {
        host: 'localhost',
        port: 9009
    },
    ssl: {
        key: fs.readFileSync('valid-ssl-key.pem', 'utf8')
        cert: fs.readFileSync('valid-ssl-cert.pem', 'utf8')
    }
}).listen(8009)

若是创建HTTPS->HTTPS的反向代理,则可以这么写:

httpProxy.createServer({
    ssl: {
        key: fs.readFileSync('valid-ssl-key.pem', 'utf8'),
        cert: fs.readFileSync('valid-ssl-cert.pem', 'utf8')
    },
    target: 'https://localhost:9010',
    secure: true // 取决于需要,可以是false. 
}).listen(443);

7、代理WebSocket

可以通过options里的ws: true来激活对websocket的支持,如下:

httpProxy.createServer({
    target: 'ws://localhost:9014',
    ws: true
}).listen(8014)

也可以这么写:

const proxy = new httpProxy.createProxyServer({
    target: {
        host: 'localhost',
        port: 9015
    }
})
const proxyServer = http.createServer((req, res) => {
    proxy.web(req, res)
})
proxyServer.on('upgrade', (req, socket, head) => {
    proxy.ws(req, socket, head)
})
proxyServer.listen(8015)


四、API

对于options的各项配置,可以参考
https://www.npmjs.com/package/http-proxy#options
模块支持的proxy事件,则如下所示:

  • error:当发送请求到目标服务器失败时会触发该事件。模块中不处理任何客户端->代理服务器,代理服务器->目标服务器的错误信息,因此推荐监听error事件并且进行处理
  • proxyReq:在数据发送前触发,允许在使用web连接的场合下有个事先修改proxyReq请求对象的机会
  • proxyReqWs:类似proxyReq,但是是针对websocket连接
  • proxyRes:如果到目标服务器的请求得到了响应,那么该事件就会被触发
  • open:一旦代理的websocket创建并且通过管道机制输入到目标websocket时,就会触发
  • close:代理websocket关闭时触发