All checks were successful
CI / test (push) Successful in 31s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3.3 KiB
3.3 KiB
CLAUDE.md — httpx
Commands
go build ./... # compile
go test ./... # all tests
go test -race ./... # tests with race detector
go test -v -run TestName ./package/ # single test
go vet ./... # static analysis
Architecture
- Module:
git.codelab.vc/pkg/httpx, Go 1.24, zero external dependencies
Client
- Core pattern: middleware is
func(http.RoundTripper) http.RoundTripper - Chain assembly order (client.go): Logging → User MW → Retry → CB → Balancer → Transport
- Retry wraps CB+Balancer so each attempt can hit a different endpoint
- Circuit breaker is per-host (
sync.Mapof host → Breaker) - Sentinel errors: canonical values live in sub-packages, root package re-exports as aliases
- balancer.Transport returns
(Middleware, *Closer)— Closer must be tracked for health checker shutdown - Client.Close() stops the health checker goroutine
- Client.Patch() — PATCH method, same pattern as Put/Post
- NewFormRequest — form-encoded request builder (
application/x-www-form-urlencoded) withGetBodyfor retry - WithMaxResponseBody — wraps
resp.Bodywithio.LimitedReaderto prevent OOM - middleware.RequestID() — propagates request ID from context to outgoing
X-Request-Idheader internal/requestid— shared context key used by bothserverandmiddlewarepackages to avoid circular imports
Server (server/)
- Core pattern: middleware is
func(http.Handler) http.Handler - Server wraps
http.Serverwithnet.Listener, graceful shutdown via signal handling, lifecycle hooks - Router wraps
http.ServeMux— supports groups with prefix + middleware inheritance,Mountfor sub-handlers,WithNotFoundHandlerfor custom 404 - Middleware chain via
Chain(A, B, C)— A outermost, C innermost (same as client side) - statusWriter wraps
http.ResponseWriterto capture status; implementsUnwrap()forhttp.ResponseController - Defaults() preset: RequestID → Recovery → Logging + production timeouts
- HealthHandler exposes
GET /healthz(liveness) andGET /readyz(readiness with pluggable checkers) - CORS middleware — preflight OPTIONS handling,
AllowOrigins,AllowMethods,AllowHeaders,ExposeHeaders,AllowCredentials,MaxAge - RateLimit middleware — per-key token bucket (
sync.Map), IP fromX-Forwarded-For,WithRate/WithBurst/WithKeyFunc, usesinternal/clock - MaxBodySize middleware — wraps
r.Bodyviahttp.MaxBytesReader - Timeout middleware — wraps
http.TimeoutHandler, returns 503 - WriteJSON / WriteError — JSON response helpers in
server/respond.go
Conventions
- Functional options for all configuration (client and server)
- Test helpers:
mockTransport(fn)wrappingmiddleware.RoundTripperFunc(client),httptest.NewRecorder/httptest.NewRequest(server) - Server tests use
waitForAddr(t, srv)helper to poll until server is ready - No external test frameworks — stdlib only
- Thread safety required (
sync.Mutex/atomic) internal/clockfor deterministic time testing
See also
AGENTS.md— universal AI agent guide with common tasks, gotchas, and ASCII diagrams