Undertowで、コンテキストパスを読み分けて違うリモートサーバーに処理を委譲するリバースプロキシを書く

モチベーション

趣味アプリのAPIサーバーとWEBサーバーが別で、こいつらを普通に運用するとWEBサーバーが認証機能まで飲み込んでしまって辛い気持ちになる予感がしたので、認証基盤を切り離すことにした。

とはいえいきなりログイン・ログアウト・会員登録や招待、ソーシャルログインや権限管理まで全部は飲み込めないので、バックエンドから特定のレスポンスヘッダーが返ってきたらセッションを発行し、削除リクエストが来たらセッションを破棄するだけの薄いものに。

これを実現するために必要なのは以下の機能。

  • セッションストア(Redisと通信するだけなのでOK)
  • リクエストヘッダーの書き換え(Undertowの機能で「こう動けばいいな」と思いながら書けばそのとおりになるのでOK)
  • レスポンスヘッダーの書き換え(ひとつ前の記事で公開済み)
  • コンテキストパスを読み分けて宛先がWEBサーバーなのかAPIサーバーなのか調べる

コンテキストパス?

URIの最初の方のやつのことを指す... と思う。 要は

  • /api ならAPIサーバーに
  • `/' ならWEBサーバーに

みたいなことがしたい。

できるよ、PathHandlerを使えばね

できた。

HttpHandler pathHandler = new PathHandler()
                .addPrefixPath("/api", new RewriteHeaderHandler(apiProxyHandler))
                .addPrefixPath("/", new RewriteHeaderHandler(webProxyHandler));

渡してる apiProxyHandlerwebProxyHandler はバックエンドアプリケーションに通信をプロキシするハンドラ。 ここらへんも基本「動け〜」と念じながら書けば動く。

ソース

ちょっとコメントも書いたから何かの助けになれば幸い。

examples/PredicateProxyHandlers.java at master · blackawa/examples · GitHub