orangeyyy
3/3/2018 - 5:10 AM

http-proxy

概述

http-proxy是非常常用的node代理工具,我们可以将它当做工具库使用,更重要的是它还支持websoket,通常我们会用它来进行反向代理或者负载均衡。

安装

我们通过下面方法进行安装:

npm install http-proxy --save

使用

http-proxy的使用也非常简单,下面我们来详细介绍关于http-proxy的使用方法。

创建proxy实例

我们通过如下方式来创建proxy实例

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

如果proxy的listen方法不调用将不会启动一个web server,proxy实例包含以下方法:

  • web(req, res, [options]) - 主要用于代理http(s)请求;
  • ws(req, res, [options]) - 主要用于代理ws(s)请求;
  • listen(port) - 启动一个webserver,并监听指定端口;
  • close([callback]) - 关闭webserver,且取消监听端口;

通常我们使用下面的方式来使用proxy实例:

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

我们有两种方式来监听proxy错误:

//方式一
proxy.on('error', function(e) {
  ...
});
//方式二
proxy.web(req, res, { target: 'http://mytarget.com:8080' }, function(e) { ... });

常用案例

创建独立proxy webserver

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

httpProxy.createProxyServer({target:'http://localhost:9000'}).listen(8000);

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);

我们在浏览器中分别访问localhost:8000 和 localhost:9000得到如下结果:

// localhost:9000
request successfully proxied!
{
  "host": "localhost:9000",
  "connection": "keep-alive",
  "upgrade-insecure-requests": "1",
  "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36",
  "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
  "accept-encoding": "gzip, deflate, br",
  "accept-language": "zh-CN,zh;q=0.9,en;q=0.8"
}
// localhost:8000
request successfully proxied!
{
  "accept-language": "zh-CN,zh;q=0.9,en;q=0.8",
  "accept-encoding": "gzip, deflate, br",
  "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
  "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36",
  "upgrade-insecure-requests": "1",
  "connection": "close",
  "host": "localhost:8000"
}

创建proxy实例代理http请求

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

var proxy = httpProxy.createProxyServer({});
http.createServer(function (req, res) {
  proxy.web(req, res, {
    target: 'http://127.0.0.1:9000'
  });
}).listen(8000);

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);

我们在浏览器中分别访问localhost:8000 和 localhost:9000得到如下结果:

// localhost:9000
request successfully proxied!
{
  "host": "localhost:9000",
  "connection": "keep-alive",
  "upgrade-insecure-requests": "1",
  "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36",
  "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
  "accept-encoding": "gzip, deflate, br",
  "accept-language": "zh-CN,zh;q=0.9,en;q=0.8"
}
// localhost:8000
request successfully proxied!
{
  "accept-language": "zh-CN,zh;q=0.9,en;q=0.8",
  "accept-encoding": "gzip, deflate, br",
  "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
  "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36",
  "upgrade-insecure-requests": "1",
  "connection": "close",
  "host": "localhost:8000"
}

proxy代理过程中更改request head

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

var proxy = httpProxy.createProxyServer({});
proxy.on('proxyReq', function(proxyReq, req, res, options) {
  proxyReq.setHeader('X-Special-Proxy-Header', 'orangeyyy');
});
http.createServer(function (req, res) {
  proxy.web(req, res, {
    target: 'http://127.0.0.1:9000'
  });
}).listen(8000);

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);

我们在浏览器中分别访问localhost:8000 和 localhost:9000得到如下结果:

// localhost:9000
request successfully proxied!
{
  "host": "localhost:9000",
  "connection": "keep-alive",
  "upgrade-insecure-requests": "1",
  "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36",
  "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
  "accept-encoding": "gzip, deflate, br",
  "accept-language": "zh-CN,zh;q=0.9,en;q=0.8"
}
// localhost:8000
request successfully proxied!
{
  "accept-language": "zh-CN,zh;q=0.9,en;q=0.8",
  "accept-encoding": "gzip, deflate, br",
  "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
  "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36",
  "upgrade-insecure-requests": "1",
  "cache-control": "no-cache",
  "pragma": "no-cache",
  "connection": "close",
  "host": "localhost:8000",
  "x-special-proxy-header": "orangeyyy"
}

使用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 // Depends on your needs, could be false. 
}).listen(443);

WebSocket

我们有两种方式来使用webSocket代理:

//方式一
httpProxy.createServer({
  target: 'ws://localhost:9014',
  ws: true
}).listen(8014);
//方式二
proxyServer.on('upgrade', function (req, socket, head) {
  proxy.ws(req, socket, head);
});

参考