ローカルで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で書けばよかった。