diff --git a/api/enriched-response.go b/api/enriched-response.go index f1e34c2..138124d 100644 --- a/api/enriched-response.go +++ b/api/enriched-response.go @@ -48,7 +48,7 @@ func (lrw *LoggingResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) if err != nil { return nil, nil, err } - log.Infof("api request: %s HIJ %s", lrw.Request.RemoteAddr, lrw.Request.RequestURI) + log.Tracer(lrw.Request.Context()).Infof("api request: %s HIJ %s", lrw.Request.RemoteAddr, lrw.Request.RequestURI) return c, b, nil } return nil, nil, errors.New("response does not implement http.Hijacker") @@ -57,12 +57,12 @@ func (lrw *LoggingResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) // RequestLogger is a logging middleware. func RequestLogger(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - log.Tracef("api request: %s ___ %s", r.RemoteAddr, r.RequestURI) + log.Tracer(r.Context()).Tracef("api request: %s ___ %s", r.RemoteAddr, r.RequestURI) lrw := NewLoggingResponseWriter(w, r) next.ServeHTTP(lrw, r) if lrw.Status != 0 { // request may have been hijacked - log.Infof("api request: %s %d %s", lrw.Request.RemoteAddr, lrw.Status, lrw.Request.RequestURI) + log.Tracer(r.Context()).Infof("api request: %s %d %s", lrw.Request.RemoteAddr, lrw.Status, lrw.Request.RequestURI) } }) } diff --git a/api/middleware.go b/api/middleware.go index 89dd465..7877037 100644 --- a/api/middleware.go +++ b/api/middleware.go @@ -1,6 +1,11 @@ package api -import "net/http" +import ( + "context" + "net/http" + + "github.com/safing/portbase/log" +) // Middleware is a function that can be added as a middleware to the API endpoint. type Middleware func(next http.Handler) http.Handler @@ -18,10 +23,30 @@ func (mwh *mwHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { handler := mwh.final // build middleware chain - for _, mw := range mwh.handlers { - handler = mw(handler) + // loop in reverse to build the handler chain in the correct order + for i := len(mwh.handlers) - 1; i >= 0; i-- { + handler = mwh.handlers[i](handler) } // start handler.ServeHTTP(w, r) } + +// ModuleWorker is an http middleware that wraps the request in a module worker. +func ModuleWorker(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + _ = module.RunWorker("http request", func(_ context.Context) error { + next.ServeHTTP(w, r) + return nil + }) + }) +} + +// LogTracer is an http middleware that attaches a log tracer to the request context. +func LogTracer(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx, tracer := log.AddTracer(r.Context()) + next.ServeHTTP(w, r.WithContext(ctx)) + tracer.Submit() + }) +} diff --git a/api/router.go b/api/router.go index bed878e..c4ad388 100644 --- a/api/router.go +++ b/api/router.go @@ -19,6 +19,8 @@ var ( middlewareHandler = &mwHandler{ final: mainMux, handlers: []Middleware{ + ModuleWorker, + LogTracer, RequestLogger, authMiddleware, },