1時に寝て何度か起きて6時半に起きた。起きてから軽く部屋の掃除をした。

echo のミドルウェア開発

go の api サーバーの開発に echo という定番のフレームワークを使っている。少し前にメンバーに認証の処理をミドルウェアとして実装してもらった。いま認可の仕組みもミドルウェアで実装しようと、いくつかソースコードを読んでいて、echo のフレームワークが提供しているミドルウェアの関数名や config には共通点があることに気付いた。echo middleware によると、20個ぐらいのミドルウェアが提供されている。例えば、適当にそのうちの3つほどを取り出すが XxxWithConfig という命名規則で config を受けとって echo.MiddlewareFunc を返すというインターフェースになっている。

func HTTPSRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc
func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc
func BodyDumpWithConfig(config BodyDumpConfig) echo.MiddlewareFunc

また config の中身をみていると、ミドルウェアの処理に必要な関数を渡すような設計になっている。複数のミドルウェアにとって共通なのは、ミドルウェアの処理を迂回する条件を実装するため middleware.Skipper という型が次のように型で定義されている。

e.Use(middleware.BasicAuthWithConfig(middleware.BasicAuthConfig{
	Skipper: func (c echo.Context) bool {
		// Skipper defines a function to skip middleware.
    },
	Validator: func(string, string, echo.Context) (bool, error) {
		// Validator is a function to validate BasicAuth credentials.
		// Required.
    },
	Realm: "Restricted",
}))

典型的なミドルウェアは次のように実装する。最初に Skipper を呼び出して処理の有無を確認する。

return func(next echo.HandlerFunc) echo.HandlerFunc {
	return func(c echo.Context) error {
		if config.Skipper(c) {
			return next(c)
		}

        // TODO: ミドルウェア本体の処理

		return next(c)
    }
}

認証のミドルウェアを実装してもらったときに、私がここまでみていなかったなということに気付いて、既存のミドルウェアを echo のそれと同じスタイルにあわせるようにリファクタリングした。自分でソースコードを読んでいるとコードレビューで気付かなかったことに気付くことが多い。自分がコードを書いているときと、コードレビューをしているときでなにかしら視点が違う。