/* Copyright (C) 2019, 2020, 2021 Monomax Software Pty Ltd * * This file is part of Dnote. * * Dnote is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Dnote is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Dnote. If not, see . */ package middleware import ( "fmt" "net/http" "time" "github.com/dnote/dnote/pkg/server/log" ) // logResponseWriter wraps http.ResponseWriter to expose HTTP status code for logging. // The optional interfaces of http.ResponseWriter are lost because of the wrapping, and // such interfaces should be implemented if needed. (i.e. http.Pusher, http.Flusher, etc.) type logResponseWriter struct { http.ResponseWriter statusCode int } func (w *logResponseWriter) WriteHeader(code int) { w.statusCode = code w.ResponseWriter.WriteHeader(code) } // logging is a logging middleware func Logging(inner http.Handler) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { start := time.Now() lw := logResponseWriter{w, http.StatusOK} inner.ServeHTTP(&lw, r) log.WithFields(log.Fields{ "origin": r.Header.Get("Origin"), "remoteAddr": lookupIP(r), "uri": r.RequestURI, "statusCode": lw.statusCode, "method": r.Method, "duration": fmt.Sprintf("%dms", time.Since(start)/1000000), "userAgent": r.Header.Get("User-Agent"), }).Info("incoming request") } }