package middleware import ( "bufio" "errors" "net" "net/http" "time" "github.com/porter-dev/porter/pkg/logger" ) type requestLoggerResponseWriter struct { http.ResponseWriter statusCode int } func newRequestLoggerResponseWriter(w http.ResponseWriter) *requestLoggerResponseWriter { return &requestLoggerResponseWriter{w, http.StatusOK} } func (rw *requestLoggerResponseWriter) WriteHeader(code int) { rw.statusCode = code rw.ResponseWriter.WriteHeader(code) } func (rw *requestLoggerResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { h, ok := rw.ResponseWriter.(http.Hijacker) if !ok { return nil, nil, errors.New("ResponseWriter Interface does not support hijacking") } return h.Hijack() } type RequestLoggerMiddleware struct { logger *logger.Logger } func NewRequestLoggerMiddleware(logger *logger.Logger) *RequestLoggerMiddleware { return &RequestLoggerMiddleware{logger} } func (mw *RequestLoggerMiddleware) Middleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() rw := newRequestLoggerResponseWriter(w) next.ServeHTTP(rw, r) latency := time.Since(start) event := mw.logger.Info().Dur("latency", latency).Int("status", rw.statusCode) logger.AddLoggingContextScopes(r.Context(), event) logger.AddLoggingRequestMeta(r, event) event.Send() }) }