シンプルなリバースプロキシ
ローカルでnginxもapacheも動かしていない状況でリバースプロキシが必要になったのでNode.jsでシンプルに。
背景
フロントエンドとバックエンドを別々に開発していると、XSRF扱いになりAPIを叩けず面倒。
解決方法を間違っている気がするが、フロントエンドのホスティングとAPIへのプロキシを同じサーバーにまとめることで回避する。
想定する構成
- localhost:80
- APIサーバが動く
- Elasticsearchなど
- localhost:8080
- フロントエンド開発中のサーバ(
npm run dev等で起動したwebpackのdevサーバーなど)
- フロントエンド開発中のサーバ(
- localhost:8090
- リバースプロキシになるサーバ
/apiが80番ポートに、それ以外の/が8080番ポートにプロキシされる- ここにアクセスして動作確認をする
localhostに限らないので、利用したい環境に合わせて以下のURLを読み替えてください。
実装
npm i http-proxy だけ必要なはず。
var http = require('http');
var fs = require('fs');
var url = require('url');
var httpProxy = require('http-proxy');
var port = process.env.PORT || 8090;
var logPath = './log';
var apiServer = 'http://localhost:80';
var frontServer = 'http://localhost:8080';
function _log(file, data, callback){
fs.appendFile(file, data, callback);
}
function log(data){
console.log(data);
_log(logPath, data, function (err) {
if (err) throw err;
});
}
function requestHandler(req, res) {
res.setHeader('Access-Control-Allow-Origin', '*');
var urlobj = url.parse(req.url, true);
log(req.method + ' ' + urlobj.pathname + '\n');
var proxy = httpProxy.createProxyServer();
if (urlobj.pathname.match(/^\/api\//)) {
// もしAPIが localhost:80/apiで動いているのならこの置換は不要
req.url = req.url.replace(/\/api\//, '');
log('replaced: ' + req.url);
proxy.web(req, res, {target: apiServer});
return;
} else {
log(req.url);
proxy.web(req, res, {target: frontServer});
}
}
http.createServer(requestHandler).listen(port);
console.log('listening http://localhost:' + port);
起動方法
上記実装をproxy.jsとして保存してnodeで起動する。
node proxy.js
ポート番号を変更するなら環境変数PORTで指定する。
PORT=1234 node proxy.js
ログはカレントディレクトリのlogに出力される。
ただアクセスされたURLを追記しているだけなので、他のフォーマットの出力にすればLogStashに流し込んだりもできるはず。
参考にしたもの
- Edisonの設定用画面として動いていたウェブサーバー
コメント
こんなものこそ練習にCommon Lispで書けばよかった。