社内プロキシに打ち勝つリバースプロキシに苦戦した話（node + http-proxy)

# はじめに
社内でフロント向け開発ツールを作成していた時、クロスドメイン問題を回避するためにフォワードプロキシが必要になった。

# やりたいこと
クライアントからのHTTPリクエストを受け、認証付き社内プロキシを経由して別サーバへフォワードする。
リクエストとレスポンスは改変しない。そのまま横流しするだけ。

# 使ったもの
- node（v8.9.3）
- [http-proxy](https://github.com/nodejitsu/node-http-proxy)

# 修正前ソース

```server.js
const httpProxy = require('http-proxy');
const http = require('http');

var proxy = httpProxy.createProxyServer({});

// http server
var httpServer = http.createServer(function (req, res) {
	res.setHeader('tekitou', 'tekitou');
    var opt = {target:'http://tekitou.com'};
    proxy.web(req, res, opt, function (err) {
		console.log(" !! translate error. ");
		console.log(err);
		res.write("<p> Translate error.</p>");
		res.write("<p>Host name : " + req.headers.host + "</p>");
		res.end();
		return;
    });
    return;
});
var port=1234
httpServer.listen(port, function () {
	console.log("-- start forward proxy server(http) . listen " + port + " port. --");
});

```

# はまったところ
- 認証付きの社内プロキシが通らない

そのままhttp-proxyでプロキシを作っても、認証付きの社内プロキシは通してくれない。
[tunnnel](https://github.com/koichik/node-tunnel)を使って認証プロキシのagentをoptionに付与する必要あり。
＜改変後＞

```server.js
const httpProxy = require('http-proxy');
const http = require('http');
// new!
const tunnel = require('tunnel');

var tunnelingAgent = tunnel.httpOverHttp({
	proxy: {
		host: 'hoge,co.jp',
		port: 1111,
		proxyAuth: 'proxyid:proxypass'
	}
});

var proxy = httpProxy.createProxyServer({});


// http server
var httpServer = http.createServer(function (req, res) {
	res.setHeader('tekitou', 'tekitou');
// new!
    var opt = {target:'http://tekitou.com' , agent:tunnelingAgent };
    proxy.web(req, res, opt, function (err) {
		console.log(" !! translate error. ");
		console.log(err);
		res.write("<p> Translate error.</p>");
		res.write("<p>Host name : " + req.headers.host + "</p>");
		res.end();
		return;
    });
    return;
});
var port=1234
httpServer.listen(port, function () {
	console.log("-- start forward proxy server(http) . listen " + port + " port. --");
});
```

- フォワード先をhttpsに向けると通らない

optionにsecure=falseとchangeOrigin=trueを付与したら通った。
さらに、tunnnelのhttpOverHttpsのagentが必要。
＜改変後＞

```server.js
const httpProxy = require('http-proxy');
const http = require('http');
const tunnel = require('tunnel');

var tunnelingAgent = tunnel.httpOverHttp({
	proxy: {
		host: 'hoge,co.jp',
		port: 1111,
		proxyAuth: 'proxyid:proxypass'
	}
});

// new!!
var tunnelingAgentForHttps = tunnel.httpOverHttps({
	proxy: {
		host: 'hoge,co.jp',
		port: 1111,
		proxyAuth: 'proxyid:proxypass'
	}
});

var proxy = httpProxy.createProxyServer({});


// http server to https
var httpServer = http.createServer(function (req, res) {
	res.setHeader('tekitou', 'tekitou');
    var opt = 
            { target:'https://tekitou.com',
              agent : tunnelingAgentForHttps ,
              secure : false,
              changeOrigin : true
             };
    proxy.web(req, res, opt, function (err) {
		console.log(" !! translate error. ");
		console.log(err);
		res.write("<p> Translate error.</p>");
		res.write("<p>Host name : " + req.headers.host + "</p>");
		res.end();
		return;
    });
    return;
});
var port=1234
httpServer.listen(port, function () {
	console.log("-- start forward proxy server(http) . listen " + port + " port. --");
});
```

# さいごに
踏み込んだ説明がなくてごめんなさい。
スマートな方法があったら教えてください。