// Package httpclient provides a resilient HTTP client with automatic retry, // circuit breaking, request-ID propagation, and typed JSON helpers. // // # Basic Usage // // client := httpclient.NewWithDefaults(logger) // resp, err := client.Do(req) // // # Typed JSON Helpers // // DoJSON decodes the response body into T without needing a manual http.Request: // // type UserResp struct{ ID, Name string } // req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) // user, err := httpclient.DoJSON[UserResp](ctx, client, req) // // DoJSONRequest marshals a request body, sends it, and decodes the response: // // result, err := httpclient.DoJSONRequest[CreateReq, CreateResp]( // ctx, client, http.MethodPost, url, createReq) // // # Request ID Propagation // // If the context carries a request ID (set by core/logz.WithRequestID or the // web/mw.RequestID middleware), it is forwarded as X-Request-ID on every // outbound attempt, including retries. // // # Resilience // // The retry loop (avast/retry-go) wraps individual HTTP attempts. The circuit // breaker (sony/gobreaker) wraps the entire retry sequence, so the breaker // opens after CBThreshold fully-exhausted retry sequences fail — not after // CBThreshold individual HTTP errors. // // # Configuration // // EINHERJAR_HTTP_CLIENT_NAME — circuit breaker label; default "http" // EINHERJAR_HTTP_TIMEOUT — total request timeout; default 30s // EINHERJAR_HTTP_DIAL_TIMEOUT — TCP dial timeout; default 5s // EINHERJAR_HTTP_MAX_RETRIES — attempts per request; default 3 // EINHERJAR_HTTP_RETRY_DELAY — base delay between retries; default 1s // EINHERJAR_HTTP_CB_THRESHOLD — consecutive failures to open breaker; default 10 // EINHERJAR_HTTP_CB_TIMEOUT — breaker half-open probe interval; default 1m package httpclient