forked from aegis/pyserveX
75 lines
1.6 KiB
Go
75 lines
1.6 KiB
Go
package middleware
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"runtime/debug"
|
|
"time"
|
|
|
|
"github.com/konduktor/konduktor/internal/logging"
|
|
)
|
|
|
|
type responseWriter struct {
|
|
http.ResponseWriter
|
|
status int
|
|
size int
|
|
}
|
|
|
|
func (rw *responseWriter) WriteHeader(code int) {
|
|
rw.status = code
|
|
rw.ResponseWriter.WriteHeader(code)
|
|
}
|
|
|
|
func (rw *responseWriter) Write(b []byte) (int, error) {
|
|
size, err := rw.ResponseWriter.Write(b)
|
|
rw.size += size
|
|
return size, err
|
|
}
|
|
|
|
func ServerHeader(next http.Handler, version string) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Server", fmt.Sprintf("konduktor/%s", version))
|
|
next.ServeHTTP(w, r)
|
|
})
|
|
}
|
|
|
|
func AccessLog(next http.Handler, logger *logging.Logger) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
start := time.Now()
|
|
|
|
wrapped := &responseWriter{
|
|
ResponseWriter: w,
|
|
status: http.StatusOK,
|
|
}
|
|
|
|
next.ServeHTTP(wrapped, r)
|
|
|
|
duration := time.Since(start)
|
|
|
|
logger.Info("HTTP request",
|
|
"method", r.Method,
|
|
"path", r.URL.Path,
|
|
"status", wrapped.status,
|
|
"duration_ms", duration.Milliseconds(),
|
|
"client_ip", r.RemoteAddr,
|
|
"user_agent", r.UserAgent(),
|
|
)
|
|
})
|
|
}
|
|
|
|
func Recovery(next http.Handler, logger *logging.Logger) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
defer func() {
|
|
if err := recover(); err != nil {
|
|
logger.Error("Panic recovered",
|
|
"error", fmt.Sprintf("%v", err),
|
|
"stack", string(debug.Stack()),
|
|
)
|
|
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
|
}
|
|
}()
|
|
|
|
next.ServeHTTP(w, r)
|
|
})
|
|
}
|