Goで始めるMiddleware
そもそもMiddlewareとは何かと言うと、私の認識ではアプリケーションの処理の前後で何らかの処理を行ったりするもの。例えば、ログを追加したりリクエストのAPIキーを認証したりする。以下の図がわかりやすい。
Laravel 5.0 - Middleware (Filter-style) | MattStauffer.com より引用
とはいえ、上記だけでは具体的にどのように実装したらイメージがつかなかったんだけど、Goの公式のwikiでいろいろ紹介していてわかりやすかったのでこれを元に簡単なサンプルを実装した。
LearnServerProgramming · golang/go Wiki · GitHub
Middlewares in Go: Best practices and examples – Nicolas Merouze
package main import ( "fmt" "net/http" "time" ) // indexHandler ... func indexHandler(w http.ResponseWriter, r *http.Request) { fmt.Println("Hello, middleware!") } // aboutHandler ... func aboutHandler(w http.ResponseWriter, r *http.Request) { fmt.Println("This is midlleware test!!") } // loggingHandler ... func loggingHandler(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { t1 := time.Now() next.ServeHTTP(w, r) t2 := time.Now() fmt.Printf("[%s] %q %v\n", r.Method, r.URL.String(), t2.Sub(t1)) } } func main() { http.HandleFunc("/", loggingHandler(indexHandler)) http.HandleFunc("/about", loggingHandler(aboutHandler)) http.ListenAndServe(":8888", nil) }
ポイントは、
http.HandlerFunc
を返すラッパーを作ること- ラッパーの中で引数の
http.HandlerFunc
を呼び出すこと
だと個人的に思った。前述の図との対応としては、処理のイメージとしてはこんな感じだろうか。Middlewareで前処理を行って、アプリケーションの処理( next.ServeHTTP(w, r)
)を行って、Middlewareで後処理を行う。
// sampleHandler ... func sampleHandler(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // 前処理 next.ServeHTTP(w, r) // 後処理 } }
まとめ
Middlewareは怖くない