ステータスコードをログに出力するhttp.Handler
http
パッケージだけでWebアプリケーションを書くとき、アクセスログの出力もhttp.Handler
で実装しようとするけど、ステータスコードを取得する手段がないことに気づく。
そこでhttp.ResponseWriter
を独自に実装することで解決できたのでメモに残す。
type logger struct {
logger *log.Logger
handler *http.Handler
}
func (l *logger) ServeHTTP(w http.ResponseWriter, r *http.Request) {
lw := &loggingResponseWriter{
ResponseWriter: w,
statusCode: http.StatusOK,
}
l.handler.ServeHTTP(lw, r)
log.Printf("status:%d path:%s\n", lw.statusCode, r.URL.Path)
}
type loggingResponseWriter struct {
http.ResponseWriter
statusCode int
}
func (w *loggingResponseWriter) WriteHeader(statusCode int) {
w.statusCode = statusCode
w.ResponseWriter.WriteHeader(statusCode)
}
logger
というhttp.Handler
は他のhttp.Handler
をラップするミドルウェアになっている。ServeHTTP
でラップしたhttp.Handler
のServeHTTP
を呼んだ後で、ログを出力している。loggingResponseWriter
という独自のhttp.ResponseWriter
を用意する。埋め込みによってinterfaceを実装している。loggingResponseWriter
はWriteHeader
だけ独自に実装し、受け取ったステータスコードを保持するようにしている。こうすることで後でログに出力できる。それ以外のメソッドは埋め込んだhttp.ResponseWriter
に委譲される。