このエントリは GMOペパボエンジニア Advent Calendar 2023 および、 Go Advent Calendar 2023 シリーズ3 の19 日目の記事です。
以下のエントリでも少し触れられていますが、現在プロキシサーバをGoで書くプロジェクトがあります。
主な実装をしているのは @pyama86 さんで、それはもうブルドーザーのように実装が進んでいるわけですが*1、私も少しだけですが書いています。
必要そうな機能をGoの薄いHTTPミドルウェアハンドラとしてOSSとしていくつか切り出していました。
そして、本体の実装が進むにつれて足りない機能を Pull Request ベースでもらったりしていたのですが、関連OSSを作る必要が発生したりなど個人リポジトリだとまとまらないため、それらをまとめるためだけにGitHub Org を新設しました。
既に私のリポジトリからのトランスファーは済んでおり、今後はこのOrg上で開発していく予定です。
どうぞよろしくお願いします。
ごく簡単にですが、置いてあるリポジトリについて紹介したいと思います。
rl
レートリミットを実現するHTTPミドルウェアハンドラです。
Goにおけるレートリミット実装としては go-chi/httprate が有名だと思います。rlもgo-chi/httprateを参考に実装しています。
rlの特徴は interface を満たす実装をつくって注入するだけで
- http.Requestの情報をもとに異なるレートリミットのルールを動的に適用できる
- 複数のレートリミットのルールを動的に重ねがけできる
というものです。
「あるホストへのアクセスだけレートリミットを緩和したい」だとか「あるIPからのアクセスだけレートリミットをかけたい」というユースケースに対応するためのものです。
rp
リバースプロキシサーバです。HTTPミドルウェアハンドラではないです。
rpの特徴は interface を満たす実装をつくって注入するだけで
- http.Requestの情報をもとに異なるUpstreamを動的に指定できる
- tls.ClientHelloInfoの情報をもとに証明書を動的に指定できる
というものです。
マルチテナントなサービスの前段などで必要になる機能を想定しています。
rc
HTTPキャッシュミドルウェアハンドラです。
rpの特徴は interface を満たす実装をつくって注入するだけで
- RFC 9111にしたがってキャッシュを使用してくれる
というものです。また、
- キャッシュルールの拡張や切り替えも可能
- http.Requestの情報をもとに異なるキャッシュルールを適用する
ということも可能です。
rcutil
rcのためのユーティリティパッケージです。
rc.Cacher の interface を満たしたディスクキャッシュ機能の提供などをしています。
mm
HTTPミドルウェアハンドラを管理するHTTPミドルウェアハンドラです。
mmの特徴は interface を満たす実装をつくって注入するだけで
- http.Requestの情報をもとに異なるHTTPミドルウェアハンドラを動的に指定できる
というものです。
動的に切り替える仕組みがないHTTPミドルウェアハンドラに動的切り替え機能を付与したいときに使うイメージです。
ちなみに、すごく短いコードなので全部貼り付けておきます。
package mm import ( "net/http" ) // Builder is a middleware builder. type Builder interface { //nostyle:ifacenames Middleware(req *http.Request) (func(next http.Handler) http.Handler, bool) } type mMw struct { builders []Builder } func newMMw(builders []Builder) *mMw { return &mMw{builders: builders} } func (mm *mMw) Handler(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { for _, b := range mm.builders { mw, ok := b.Middleware(r) if !ok { continue } next = mw(next) } next.ServeHTTP(w, r) }) } // New returns a new middleware-middleware. func New(builders ...Builder) func(next http.Handler) http.Handler { mm := newMMw(builders) return mm.Handler }
以上、と思ったら、先ほど rlutils というパッケージが誕生していました。
2manymws*2、どうぞよろしくお願いします。
*1:わかる人にはわかると思います。是非間近で見てほしいので、こちらから応募してください。https://recruit.pepabo.com/