A lightweight Go HTTP client with configurable retries, rate limiting, timeouts, and User-Agent. Uses only the standard library.
go get github.com/MinatoAka/myhttpclient := myhttp.New(
myhttp.WithRetry(3, time.Second),
myhttp.WithRateLimit(5),
myhttp.WithTimeout(10*time.Second),
myhttp.WithUserAgent("myapp/1.0"),
)
resp, err := client.Get("https://example.com")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()Import github.com/MinatoAka/myhttp and time in your Go file.
| Option | Description | Default |
|---|---|---|
WithRetry(maxRetries int, baseWait time.Duration) |
Retry network errors and HTTP 5xx. 0 disables retries |
3, 1s |
WithRateLimit(reqPerSec int) |
Max requests per second per client. 0 disables |
0 (disabled) |
WithTimeout(d time.Duration) |
Timeout for the whole call, including retries | 15s |
WithUserAgent(ua string) |
Default User-Agent header |
myhttp/1.0 |
myhttp.New() with no options is valid — all defaults apply.
| Method | Signature |
|---|---|
New |
New(opts ...Option) *Client |
Get |
Get(url string) (*http.Response, error) |
Do |
Do(req *http.Request) (*http.Response, error) |
Get is a shortcut. For POST, PUT, DELETE, or any request with custom headers, build an *http.Request and send it with Do.
Retries
- Triggered by network errors, HTTP
5xx, and HTTP429(rate limited). - Other
4xx(400/401/403/404) are returned immediately — checkresp.StatusCodeyourself. - If the server sends
Retry-After, that value is used instead of backoff. Both formats are supported: delta-seconds (5) and HTTP-date. - Otherwise backoff doubles from
baseWait(1s → 2s → 4s) plus 0–500ms jitter, capped at 60s. - Sleep between attempts is context-aware: cancelling the request stops retries immediately.
- When retries are exhausted,
Get/Doreturn a nil response and an error wrapping the last failure. - Request bodies are buffered once and replayed on each attempt, so POST/PUT retries are safe.
WithRetry(0, ...)disables the retry layer entirely.
Rate limiting
- Applied once per
Get/Docall, before the retry layer. Retries inside a call are not gated again. - Blocks (sleeps) until the next slot is free; it never returns an error.
- Shared across all goroutines using the same client.
Timeout
WithTimeoutcovers the entire call, including all retries and backoff sleeps — not each individual attempt.- Example:
WithRetry(3, time.Second)can sleep ~7s in backoff alone, so keep the timeout comfortably above that.
Response body
- The caller closes
resp.Bodyon success. - Bodies from failed attempts are closed automatically before retrying.
go test ./...