本稿では、UNIXドメインソケットで待ち受けているHTTPサーバを対象とした、リバースプロキシの立て方を説明する。リバースプロキシを立てるにあたってはhttp-proxyパッケージを使う。本稿のサンプルコードはTypeScriptで書く。
本稿のゴール
UNIXドメインソケットでListenしているHTTPサーバを対象とした、リバースプロキシをNode.jsで作れるようになる。
http-proxyをUNIXドメインソケットに向ける実装例
下記に示すコードは、http-proxyでプロキシサーバを立て、UNIXドメインソケットでListenしているHTTPサーバにリクエストを転送するものである。
import http, {IncomingMessage, ServerResponse} from 'http'
import httpProxy from 'http-proxy'
import fs from 'fs'
const socketFile = '/tmp/http.sock'
fs.existsSync(socketFile) && fs.unlinkSync(socketFile) // ファイルがあるとHTTPサーバが起動しないため
// HTTPサーバ(Unixドメインソケットでリッスンしている)
http.createServer((req: IncomingMessage, res: ServerResponse): void => {
res.write(JSON.stringify(req.headers, null, 2)) // リクエストヘッダをレスポンスBodyに出す
res.end()
}).listen(socketFile)
// プロキシサーバ
const proxy = httpProxy.createProxyServer()
http.createServer((req: IncomingMessage, res: ServerResponse): void => {
proxy.web(req, res, {
target: {
// @ts-ignore
socketPath: socketFile,
},
})
}).listen(8000)
ポイントは、proxy.web
の第3引数のオプションにtarget.socketPath
を与え、そこにソケットファイルのパスを指定するところ。
@ts-ignore
を付けている理由
そもそもtarget
はstring | url.URL
しか受け付けないインターフェイスになっている。しかし、{ socketPath: string }
型を渡すと、内部実装上ソケットファイルを読み込めるようにはなっている。@ts-ignore
をつけることで、string | url.URL
の制限を迂回している。当然、型安全性は犠牲にしている。加えて、言うなれば、プライベートAPIを叩いているような形にはなる。インターフェイスの仕様が変更されたら、この方法は使えなくなるかもしれない。