/* Copyright 2025 Dnote Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 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") } }