Files
httpx/CLAUDE.md
Aleksey Shakhmatov f609b12c2f
All checks were successful
CI / test (push) Successful in 38s
Publish / publish (push) Successful in 35s
Update CLAUDE.md and README for revised behavior
Document RateLimit's RemoteAddr-by-default keying and WithTrustedProxies, and
that WithMaxResponseBody returns ErrResponseTooLarge rather than truncating.
2026-05-23 13:47:43 +03:00

3.4 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.Map of 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) with GetBody for retry
  • WithMaxResponseBody — caps resp.Body reads; returns ErrResponseTooLarge (not silent truncation) when exceeded
  • middleware.RequestID() — propagates request ID from context to outgoing X-Request-Id header
  • internal/requestid — shared context key used by both server and middleware packages to avoid circular imports

Server (server/)

  • Core pattern: middleware is func(http.Handler) http.Handler
  • Server wraps http.Server with net.Listener, graceful shutdown via signal handling, lifecycle hooks
  • Router wraps http.ServeMux — supports groups with prefix + middleware inheritance, Mount for sub-handlers, WithNotFoundHandler for custom 404
  • Middleware chain via Chain(A, B, C) — A outermost, C innermost (same as client side)
  • statusWriter wraps http.ResponseWriter to capture status; implements Unwrap() for http.ResponseController
  • Defaults() preset: RequestID → Recovery → Logging + production timeouts
  • HealthHandler exposes GET /healthz (liveness) and GET /readyz (readiness with pluggable checkers)
  • CORS middleware — preflight OPTIONS handling, AllowOrigins, AllowMethods, AllowHeaders, ExposeHeaders, AllowCredentials, MaxAge
  • RateLimit middleware — per-key token bucket (sync.Map), keys on RemoteAddr by default; X-Forwarded-For is honored only via WithTrustedProxies; WithRate/WithBurst/WithKeyFunc/WithMaxKeys, uses internal/clock, idle buckets evicted to bound memory
  • MaxBodySize middleware — wraps r.Body via http.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) wrapping middleware.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/clock for deterministic time testing

See also

  • AGENTS.md — universal AI agent guide with common tasks, gotchas, and ASCII diagrams