Files
httpx/CLAUDE.md
Aleksey Shakhmatov 89cfc38f0e
All checks were successful
CI / test (push) Successful in 30s
Update documentation with new client and server features
README: add PATCH, NewFormRequest, CORS, RateLimit, MaxBodySize,
Timeout, WriteJSON/WriteError, request ID propagation, response body
limit, and custom 404 handler examples. CLAUDE.md: document new
architecture details for all added components.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 21:55:15 +03:00

3.2 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 — wraps resp.Body with io.LimitedReader to prevent OOM
  • 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), IP from X-Forwarded-For, WithRate/WithBurst/WithKeyFunc, uses internal/clock
  • 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