-
Release v1.0.0 Stable
released this
2026-05-11 19:51:01 -06:00 | 1 commits to main since this releasev1.0.0
code.nochebuena.dev/go/httpclientOverview
httpclientv1.0.0 commits the HTTP client API as stable. All v0.9.0 roadmap items are
resolved. The module wrapsnet/httpwith automatic retry, circuit breaking, request-ID
propagation, and generic typed JSON helpers for both outbound requests and responses.What Changed Since v0.9.0
Retry-on-429 with Retry-After
The retry loop now handles HTTP 429 Too Many Requests. Previously only network errors and
>= 500responses triggered a retry; 429 was returned immediately to the caller.When the server responds with 429 and includes a
Retry-Afterheader (integer seconds),
that duration is used as the delay before the next attempt. Without the header, the
configuredBackOffDelayapplies as usual.// Server responds: 429 Too Many Requests + Retry-After: 5 // Client waits 5 seconds, then retries automatically.DoJSONRequest[Req, Resp any]
New free generic function complementing
DoJSON. Use it for POST/PUT/PATCH calls where
the request also carries a JSON body:// Before (manual boilerplate every time): data, _ := json.Marshal(myReq) req, _ := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(data)) req.Header.Set("Content-Type", "application/json") resp, err := httpclient.DoJSON[MyResponse](ctx, client, req) // After: resp, err := httpclient.DoJSONRequest[MyRequest, MyResponse](ctx, client, "POST", url, myReq)Use
DoJSONfor GET/DELETE (no request body); useDoJSONRequestfor POST/PUT/PATCH.Dependency bumps
logzandxerrorspromoted to v1.0.0.Roadmap items resolved
Item Resolution Retry-on-429 with Retry-After✅ Done — respects header when present, falls back to BackOffDelay DoJSONRequest[Req, Resp]✅ Done — serialises body, sets Content-Type, delegates to DoJSON Circuit breaker state metrics ❌ No — exposing gobreaker.Statecouples the Client interface to a third-party type; state transitions are already logged at Warn levelDoStream❌ No — streaming is a fundamentally different API contract; use client.Dodirectly for streaming responsesProduction feedback on defaults ✅ Validated as-is — 30s/5s/3 retries/1s delay/10 CB threshold/1m CB timeout confirmed in production Full API (stable)
Client—Do(req *http.Request) (*http.Response, error).Config—Name,Timeout,DialTimeout,MaxRetries,RetryDelay,CBThreshold,CBTimeout; env-tag support.New(logger logz.Logger, cfg Config) Client— constructor with circuit breaker + retry.NewWithDefaults(logger logz.Logger) Client— convenience constructor with production defaults.DefaultConfig() Config— returns the default configuration values.DoJSON[T any](ctx, client, req) (*T, error)— executes a request and decodes the JSON response intoT. Use for GET/DELETE.DoJSONRequest[Req, Resp any](ctx, client, method, url, body) (*Resp, error)— serialisesbodyas JSON, constructs the request, and decodes the response. Use for POST/PUT/PATCH.MapStatusToError(code int, msg string) error— maps HTTP status codes to xerrors:404→ErrNotFound,400→ErrInvalidInput,401→ErrUnauthorized,403→ErrPermissionDenied,409→ErrAlreadyExists,429→ErrUnavailable, others →ErrInternal.Migration from v0.9.0
No breaking changes.
DoJSONRequestis a new addition; existing code usingDoJSONis unaffected. The retry-on-429 behavior is a change inDo— callers that previously handled 429 manually after the call should review whether that handling is still needed.go get code.nochebuena.dev/go/httpclient@v1.0.0Downloads