// ServeHTTPContext implements the httpx.Handler interface. It recovers from // panics and returns an error for upstream middleware to handle. func (h *Recovery) ServeHTTPContext(ctx context.Context, w http.ResponseWriter, r *http.Request) (err error) { ctx = reporter.WithReporter(ctx, h.Reporter) // Add the request to the context. reporter.AddRequest(ctx, r) // Add the request id reporter.AddContext(ctx, "request_id", httpx.RequestID(ctx)) defer func() { if v := recover(); v != nil { err = fmt.Errorf("%v", v) if v, ok := v.(error); ok { err = v } reporter.Report(ctx, err) return } }() err = h.handler.ServeHTTPContext(ctx, w, r) return }
// PrefixRequestID adds the request as a prefix to the log15.Logger. func PrefixRequestID(h httpx.Handler) httpx.Handler { return httpx.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error { if l, ok := logger.FromContext(ctx); ok { if l, ok := l.(log15.Logger); ok { ctx = logger.WithLogger(ctx, l.New("request_id", httpx.RequestID(ctx))) } } return h.ServeHTTPContext(ctx, w, r) }) }
func (h *Logger) ServeHTTPContext(ctx context.Context, w http.ResponseWriter, r *http.Request) error { l := logger.New(log.New(h.Device, fmt.Sprintf("request_id=%s ", httpx.RequestID(ctx)), 0)) ctx = logger.WithLogger(ctx, l) l.Log( "at", "request", "method", r.Method, "path", fmt.Sprintf(`"%s"`, r.URL.Path), ) return h.handler.ServeHTTPContext(ctx, w, r) }
// WithRequest adds information about the http.Request to reported errors. func WithRequest(h httpx.Handler) httpx.Handler { return httpx.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error { ctx = httpx.WithRequest(ctx, r) // Add the request to the context. reporter.AddRequest(ctx, r) // Add the request id reporter.AddContext(ctx, "request_id", httpx.RequestID(ctx)) return h.ServeHTTPContext(ctx, w, r) }) }
// Common wraps the httpx.Handler with some common middleware. func Common(h httpx.Handler, opts CommonOpts) http.Handler { l := &log{opts.Logger} // Recover from panics. h = middleware.Recover(h, opts.Reporter) // Add a logger to the context. h = middleware.LogTo(h, func(ctx context.Context, r *http.Request) logger.Logger { return l.New("request_id", httpx.RequestID(ctx)) }) // Wrap the route in middleware to add a context.Context. return middleware.BackgroundContext(h) }
func TestRequestID(t *testing.T) { m := &RequestID{ handler: httpx.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error { requestID := httpx.RequestID(ctx) if got, want := requestID, "1234"; got != want { t.Fatalf("RequestID => %s; want %s", got, want) } return nil }), } ctx := context.Background() resp := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/", nil) req.Header.Set("X-Request-ID", "1234") if err := m.ServeHTTPContext(ctx, resp, req); err != nil { t.Fatal(err) } }
func stdLogger(out io.Writer) func(context.Context, *http.Request) logger.Logger { return func(ctx context.Context, r *http.Request) logger.Logger { return logger.New(log.New(out, fmt.Sprintf("request_id=%s ", httpx.RequestID(ctx)), 0)) } }