Add client RequestID middleware for cross-service propagation
Introduces internal/requestid package with shared context key to avoid circular imports between server and middleware packages. Server's RequestID middleware now uses the shared key. Client middleware picks up the ID from context and sets X-Request-Id on outgoing requests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
69
middleware/requestid_test.go
Normal file
69
middleware/requestid_test.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package middleware_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"git.codelab.vc/pkg/httpx/internal/requestid"
|
||||
"git.codelab.vc/pkg/httpx/middleware"
|
||||
)
|
||||
|
||||
func TestRequestID(t *testing.T) {
|
||||
t.Run("propagates ID from context", func(t *testing.T) {
|
||||
var gotHeader string
|
||||
base := middleware.RoundTripperFunc(func(req *http.Request) (*http.Response, error) {
|
||||
gotHeader = req.Header.Get("X-Request-Id")
|
||||
return &http.Response{StatusCode: http.StatusOK, Body: http.NoBody}, nil
|
||||
})
|
||||
|
||||
mw := middleware.RequestID()(base)
|
||||
|
||||
ctx := requestid.NewContext(context.Background(), "test-id-123")
|
||||
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, "http://example.com", nil)
|
||||
_, err := mw.RoundTrip(req)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if gotHeader != "test-id-123" {
|
||||
t.Fatalf("X-Request-Id = %q, want %q", gotHeader, "test-id-123")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("no ID in context skips header", func(t *testing.T) {
|
||||
var gotHeader string
|
||||
base := middleware.RoundTripperFunc(func(req *http.Request) (*http.Response, error) {
|
||||
gotHeader = req.Header.Get("X-Request-Id")
|
||||
return &http.Response{StatusCode: http.StatusOK, Body: http.NoBody}, nil
|
||||
})
|
||||
|
||||
mw := middleware.RequestID()(base)
|
||||
|
||||
req, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "http://example.com", nil)
|
||||
_, err := mw.RoundTrip(req)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if gotHeader != "" {
|
||||
t.Fatalf("expected no X-Request-Id header, got %q", gotHeader)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("does not mutate original request", func(t *testing.T) {
|
||||
base := middleware.RoundTripperFunc(func(req *http.Request) (*http.Response, error) {
|
||||
return &http.Response{StatusCode: http.StatusOK, Body: http.NoBody}, nil
|
||||
})
|
||||
|
||||
mw := middleware.RequestID()(base)
|
||||
|
||||
ctx := requestid.NewContext(context.Background(), "test-id")
|
||||
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, "http://example.com", nil)
|
||||
_, _ = mw.RoundTrip(req)
|
||||
|
||||
if req.Header.Get("X-Request-Id") != "" {
|
||||
t.Fatal("original request was mutated")
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user