client

package
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Aug 18, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

README

client

The outbound half of httpx: a production-tuned HTTP client with a timeout you can't turn off, a circuit-breaker seam, and logging that inherits your redaction.

Status: ships with the httpx module. Module overview: the httpx README.

TL;DR

go get github.com/Wigata-Intech/w-tools/httpx
  • Pooling tuned for services: 100 idle connections per host (stdlib default: 2), TLS 1.2+ with session cache, Config.TLS for internal CAs/mTLS
  • A mandatory timeout — a hung upstream can't hang your goroutine
  • Config.Breaker seam: anything with Allow() error / Record(err error) plugs in; x/circuitbreaker satisfies it natively; open circuit → ErrCircuitOpen in nanoseconds
  • Outbound traceparent with fresh span ids; a caller-set header is never overwritten
  • Opt-in request/response logging where redaction follows your logger: query strings logged as parsed maps (?api_key= redacts), response capture Content-Length-gated so streaming/SSE is never buffered
  • Ctx-first verbs including RFC 10008 QUERY

How to use with httpx

Server and client share one logger, so redaction and trace ids flow through both directions of a request:

log := logger.New(logger.Config{App: "my-service", Redact: logger.RedactConfig{Redacted: []string{"api_key"}}})
upstream := client.New(client.Config{Log: log.Slog(), Breaker: breaker})

// inside a handler: the outbound call carries the inbound trace
resp, err := upstream.Get(r.Context(), "https://api.upstream.example/orders")

How to use standalone

Nothing here needs the httpx server — any Go program gets the same client:

c := client.New(client.Config{}) // production transport + default timeout, zero config required
resp, err := c.Get(ctx, url)

Build one client per upstream at boot and reuse it everywhere — the pool is the point; per-request clients rebuild pools and defeat every number above.

Documentation

Overview

Package client is httpx's outbound side: an http.Client wrapper with production transport tuning, a mandatory timeout, a circuit-breaker hook, W3C traceparent propagation from the request context, and opt-in request/response logging that inherits the supplied logger's redaction.

Index

Constants

View Source
const (
	DefaultTimeout             = 30 * time.Second
	DefaultMaxIdleConnsPerHost = 100 // stdlib default: 2
	DefaultIdleConnTimeout     = 90 * time.Second
)

Defaults applied by New wherever config is zero-valued. "No timeout" is not expressible: that footgun stays in the stdlib.

Variables

View Source
var ErrCircuitOpen = errors.New("httpx/client: circuit open")

ErrCircuitOpen is returned by Do before the network is touched when the breaker rejects the attempt; the breaker's own error is wrapped alongside it.

Functions

This section is empty.

Types

type Breaker

type Breaker interface {
	Allow() error
	Record(err error)
}

Breaker is the circuit-breaker hook, consulted per request when set. x/circuitbreaker implements it structurally; any breaker with this shape wires in — this package never imports one.

type Client

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

Client is an outbound HTTP client with tuned pooling. Use it like http.Client: Do for full control, the ctx-first verbs for convenience.

func New

func New(cfg Config) *Client

New returns a Client ready for production traffic: keep-alive pooling sized for real services, TLS session resumption, and a hard timeout.

func (*Client) Do

func (c *Client) Do(req *http.Request) (*http.Response, error)

Do sends the request. The breaker, when set, is consulted before the network and told the transport outcome after — a received response of any status records success; status policy stays with the caller. A trace carried by the request context (middleware.Trace) is propagated as a traceparent header with a freshly minted span id, unless the caller already set one.

Like http.Client.Do, this consumes and may replace req.Body; the request must not be reused.

func (*Client) Get

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

Get issues a GET to url.

func (*Client) Post

func (c *Client) Post(ctx context.Context, url, contentType string, body io.Reader) (*http.Response, error)

Post issues a POST with the given body.

func (*Client) Query

func (c *Client) Query(ctx context.Context, url, contentType string, body io.Reader) (*http.Response, error)

Query issues a QUERY (RFC 10008): a safe, idempotent query carried in the request body.

type Config

type Config struct {
	// Timeout is the total per-attempt time. Zero means DefaultTimeout.
	Timeout time.Duration

	MaxIdleConnsPerHost int
	IdleConnTimeout     time.Duration

	// TLS overrides the default TLS settings (TLS 1.2 floor, session
	// resumption cache). Set it for internal CAs (RootCAs) or mTLS
	// client certificates (Certificates); when set it is used as-is —
	// the caller owns it fully. Public APIs need nothing here: servers
	// present their certificates and the OS trust store verifies them.
	TLS *tls.Config

	// Breaker is consulted per request when set. Nil = no breaking.
	Breaker Breaker

	// Log enables outbound logging: nil is silent, set means one line
	// per call. Redaction travels inside the handler, so a logger built
	// by w-tools/logger applies its rules to query params and captured
	// bodies automatically.
	Log *slog.Logger

	// Body capture is off by default. Captured JSON bodies are logged
	// as structured attrs; non-JSON bodies log as size only, never raw.
	// Response capture never gates the caller: only bodies with a
	// declared Content-Length within MaxBody are read; streaming and
	// chunked responses are never touched.
	LogRequestBody  bool
	LogResponseBody bool

	// MaxBody caps each captured body. Default httpx.DefaultMaxBody.
	MaxBody int
}

Config configures New. Every zero value is a production default.

Jump to

Keyboard shortcuts

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