httpclient

package
v0.26.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 25, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package httpclient is a fluent wrapper around net/http modelled on Laravel's Http facade.

Compared to net/http directly, the wrapper handles JSON marshalling, query strings, headers, basic/bearer auth, timeouts, and retries with exponential backoff — common boilerplate that every service caller writes by hand.

Usage:

resp, err := httpclient.New().
    Timeout(5 * time.Second).
    Retry(3).
    BaseURL("https://api.example.com").
    BearerToken(tok).
    Get(ctx, "/users/42")
if err != nil { return err }
var u User
if err := resp.JSON(&u); err != nil { return err }

Errors from the underlying transport are wrapped; non-2xx responses are NOT errors (callers inspect resp.Status()).

Safety notes (caller responsibilities)

SSRF: this client issues requests to whatever URL it is given and uses the stdlib http.Client default redirect policy, which follows up to 10 redirects without restriction. It does NOT validate the destination host, block private/link-local/loopback ranges, or pin redirects to an allowlist. If you pass user-controlled URLs (or talk to an upstream that can redirect you to one), guard against SSRF at the caller level — e.g. validate the host, or install a Transport whose DialContext rejects private address ranges. See Transport.

Retry idempotency: Retry retries on transport errors and on 5xx / 429 responses for every verb, including PostJSON/PutJSON/PatchJSON. The request body is buffered once and replayed on each attempt. Retrying a non-idempotent write can cause duplicate side effects if the upstream is not idempotent or does not de-duplicate (e.g. via an idempotency key). Only enable Retry for such verbs against upstreams you know are safe to retry.

Response cap: response bodies are bounded by MaxResponseBytes (DefaultMaxResponseBytes by default) so a hostile or runaway server cannot OOM the process. Bodies exceeding the cap fail with ErrResponseTooLarge.

Index

Constants

View Source
const DefaultMaxResponseBytes int64 = 10 << 20 // 10 MiB

DefaultMaxResponseBytes caps how much of a response body is buffered into memory, guarding against a hostile or runaway server OOMing the process. Override per-client with MaxResponseBytes.

Variables

View Source
var ErrResponseTooLarge = errors.New("httpclient: response body exceeds limit")

ErrResponseTooLarge is returned when a response body exceeds the configured cap (see MaxResponseBytes).

Functions

This section is empty.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is an immutable HTTP client configuration. Each setter returns a clone so chains compose safely:

base := httpclient.New().BaseURL("https://api.x.com").BearerToken(t)
a := base.Header("X-Trace", "1") // doesn't mutate base

func New

func New() *Client

New returns a Client with safe defaults (10s timeout, no retries, stdlib transport).

func (*Client) Backoff

func (c *Client) Backoff(d time.Duration) *Client

Backoff sets the initial retry delay; subsequent attempts double it.

func (*Client) BaseURL

func (c *Client) BaseURL(u string) *Client

BaseURL sets the prefix for relative paths.

func (*Client) BasicAuth

func (c *Client) BasicAuth(user, password string) *Client

BasicAuth sets the Authorization header with HTTP Basic credentials.

func (*Client) BearerToken

func (c *Client) BearerToken(t string) *Client

BearerToken sets Authorization: Bearer <token>.

func (*Client) Delete

func (c *Client) Delete(ctx context.Context, path string) (*Response, error)

Delete issues a DELETE.

func (*Client) Get

func (c *Client) Get(ctx context.Context, path string) (*Response, error)

Get issues a GET to path.

func (*Client) Header

func (c *Client) Header(k, v string) *Client

Header adds (or overwrites) a header.

func (*Client) Headers

func (c *Client) Headers(m map[string]string) *Client

Headers adds multiple headers in one call.

func (*Client) MaxResponseBytes added in v0.20.0

func (c *Client) MaxResponseBytes(n int64) *Client

MaxResponseBytes caps how many bytes of a response body are buffered into memory. A response larger than the cap fails with ErrResponseTooLarge instead of consuming unbounded memory. The default is DefaultMaxResponseBytes (10 MiB); pass a value <= 0 to disable the cap (opt-out) when you trust the upstream.

func (*Client) PatchJSON

func (c *Client) PatchJSON(ctx context.Context, path string, body any) (*Response, error)

PatchJSON marshals body as JSON and PATCHes it.

func (*Client) PostJSON

func (c *Client) PostJSON(ctx context.Context, path string, body any) (*Response, error)

PostJSON marshals body as JSON and POSTs it.

func (*Client) PutJSON

func (c *Client) PutJSON(ctx context.Context, path string, body any) (*Response, error)

PutJSON marshals body as JSON and PUTs it.

func (*Client) Query

func (c *Client) Query(k, v string) *Client

Query adds a URL query parameter (appends — call multiple times for repeated keys).

func (*Client) Retry

func (c *Client) Retry(n int) *Client

Retry sets how many times to retry on transport errors or 5xx / 429 responses. Default 0 (no retries). Backoff grows exponentially from the value passed to Backoff().

func (*Client) Timeout

func (c *Client) Timeout(d time.Duration) *Client

Timeout overrides the per-request timeout.

func (*Client) Transport

func (c *Client) Transport(rt http.RoundTripper) *Client

Transport replaces the underlying http.RoundTripper (e.g. for mocks or to enforce TLS pinning).

type Response

type Response struct {
	// contains filtered or unexported fields
}

Response wraps an http.Response with helpers and an already-read body so callers don't need to remember to Close.

func (*Response) Body

func (r *Response) Body() []byte

Body returns the raw body bytes (already drained from the wire).

func (*Response) Header

func (r *Response) Header(k string) string

Header returns the response header value.

func (*Response) JSON

func (r *Response) JSON(dst any) error

JSON decodes the body into dst.

func (*Response) OK

func (r *Response) OK() bool

OK reports whether the status is 2xx.

func (*Response) Status

func (r *Response) Status() int

Status returns the HTTP status code.

func (*Response) String

func (r *Response) String() string

String returns the body as a string.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL