feat: add unique ids to all HTTP requests (#3845)

This commit is contained in:
Colin Adler
2022-09-02 13:04:29 -05:00
committed by GitHub
parent de219d966d
commit ff0aa8d742
4 changed files with 70 additions and 0 deletions
+2
View File
@@ -12,6 +12,7 @@ import (
"cdr.dev/slog"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/coderd/httpmw"
)
type RequestParams struct {
@@ -69,6 +70,7 @@ func InitRequest[T Auditable](w http.ResponseWriter, p *RequestParams) (*Request
Action: p.Action,
Diff: diffRaw,
StatusCode: int32(sw.Status),
RequestID: httpmw.RequestID(p.Request),
})
if err != nil {
p.Log.Error(ctx, "export audit log", slog.Error(err))
+1
View File
@@ -155,6 +155,7 @@ func New(options *Options) *API {
apiKeyMiddleware := httpmw.ExtractAPIKey(options.Database, oauthConfigs, false)
r.Use(
httpmw.AttachRequestID,
httpmw.Recover(api.Logger),
httpmw.Logger(api.Logger),
httpmw.Prometheus(options.PrometheusRegistry),
+34
View File
@@ -0,0 +1,34 @@
package httpmw
import (
"context"
"net/http"
"github.com/google/uuid"
"cdr.dev/slog"
)
type requestIDContextKey struct{}
// RequestID returns the ID of the request.
func RequestID(r *http.Request) uuid.UUID {
rid, ok := r.Context().Value(requestIDContextKey{}).(uuid.UUID)
if !ok {
panic("developer error: request id middleware not provided")
}
return rid
}
// AttachRequestID adds a request ID to each HTTP request.
func AttachRequestID(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rid := uuid.New()
ctx := context.WithValue(r.Context(), requestIDContextKey{}, rid)
ctx = slog.With(ctx, slog.F("request_id", rid))
rw.Header().Set("X-Coder-Request-Id", rid.String())
next.ServeHTTP(rw, r.WithContext(ctx))
})
}
+33
View File
@@ -0,0 +1,33 @@
package httpmw_test
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/go-chi/chi/v5"
"github.com/stretchr/testify/require"
"github.com/coder/coder/coderd/httpmw"
)
func TestRequestID(t *testing.T) {
t.Parallel()
rtr := chi.NewRouter()
rtr.Use(httpmw.AttachRequestID)
rtr.Get("/", func(w http.ResponseWriter, r *http.Request) {
rid := httpmw.RequestID(r)
w.WriteHeader(http.StatusOK)
w.Write([]byte(rid.String()))
})
r := httptest.NewRequest("GET", "/", nil)
rw := httptest.NewRecorder()
rtr.ServeHTTP(rw, r)
res := rw.Result()
defer res.Body.Close()
require.Equal(t, http.StatusOK, res.StatusCode)
require.NotEmpty(t, res.Header.Get("X-Coder-Request-ID"))
require.NotEmpty(t, rw.Body.Bytes())
}