httpclient

package
v0.30.0 Latest Latest
Warning

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

Go to latest
Published: May 3, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// DefaultTimeout is the default request timeout duration
	DefaultTimeout = 30 * time.Second

	// DefaultMaxRetries is the default maximum number of retries for failed requests
	DefaultMaxRetries = 0

	// DefaultRetryDelay is the default delay between retries
	DefaultRetryDelay = 1 * time.Second
)
View Source
const (
	// HeaderXRequestID is the standard header name for request tracing
	HeaderXRequestID = gobrickstrace.HeaderXRequestID
	// HeaderTraceParent is the W3C trace context header name
	HeaderTraceParent = gobrickstrace.HeaderTraceParent
	// HeaderTraceState is the W3C trace context "tracestate" header name
	HeaderTraceState = gobrickstrace.HeaderTraceState
)
View Source
const DefaultMaxJOSEBodyBytes int64 = 10 << 20 // 10 MiB

DefaultMaxJOSEBodyBytes caps the size of an inbound JOSE response body when no explicit MaxResponseBytes is set on JOSETransport. 10 MiB is comfortably larger than any expected VTS-style payload (token responses are typically <2 KiB) but small enough to bound peak memory if a counterparty (or attacker) sends a malicious response. Defense-in-depth against memory exhaustion.

Variables

This section is empty.

Functions

func EnsureTraceID

func EnsureTraceID(ctx context.Context) string

EnsureTraceID returns an existing trace ID from context or generates a new one

func GenerateTraceParent

func GenerateTraceParent() string

GenerateTraceParent creates a minimal W3C traceparent header value. Format: version(2)-trace-id(32)-span-id(16)-flags(2), e.g., "00-<32>-<16>-01"

func IsErrorType

func IsErrorType(err error, errorType ErrorType) bool

IsErrorType checks if an error is of a specific type

func IsHTTPStatusError

func IsHTTPStatusError(err error, statusCode int) bool

IsHTTPStatusError checks if an error is an HTTP error with a specific status code

func IsJOSEError added in v0.30.0

func IsJOSEError(err error) bool

IsJOSEError reports whether err is a JOSE crypto failure — kept as a thin re-export of jose.IsError for discoverability from the httpclient package, since transport callers typically already import httpclient and may not realize the canonical helper lives in jose.

func IsSuccessStatus

func IsSuccessStatus(statusCode int) bool

IsSuccessStatus checks if a status code represents success (2xx)

func TraceIDFromContext

func TraceIDFromContext(ctx context.Context) (string, bool)

TraceIDFromContext returns a trace ID from context if present

func TraceParentFromContext

func TraceParentFromContext(ctx context.Context) (string, bool)

TraceParentFromContext returns a traceparent from context if present

func TraceStateFromContext

func TraceStateFromContext(ctx context.Context) (string, bool)

TraceStateFromContext returns a tracestate from context if present

func WithTraceID

func WithTraceID(ctx context.Context, traceID string) context.Context

WithTraceID adds a trace ID to the context for HTTP client propagation

func WithTraceParent

func WithTraceParent(ctx context.Context, traceParent string) context.Context

WithTraceParent adds a W3C traceparent value to the context

func WithTraceState

func WithTraceState(ctx context.Context, traceState string) context.Context

WithTraceState adds a W3C tracestate value to the context

Types

type BasicAuth

type BasicAuth struct {
	Username string
	Password string
}

BasicAuth contains basic authentication credentials

type Builder

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

Builder provides a fluent interface for configuring the REST client

func NewBuilder

func NewBuilder(log logger.Logger) *Builder

NewBuilder creates a new client builder

func (*Builder) Build

func (b *Builder) Build() Client

Build creates the REST client with the configured options

func (*Builder) WithBasicAuth

func (b *Builder) WithBasicAuth(username, password string) *Builder

WithBasicAuth sets basic authentication credentials

func (*Builder) WithDefaultHeader

func (b *Builder) WithDefaultHeader(key, value string) *Builder

WithDefaultHeader adds a default header that will be sent with all requests

func (*Builder) WithHTTPClient

func (b *Builder) WithHTTPClient(client *nethttp.Client) *Builder

WithHTTPClient allows providing a custom *http.Client instance. If the provided client's Timeout is zero, the builder applies its configured Timeout; otherwise it is used as-is. The client's Transport is preserved unless explicitly overridden via WithTransport.

func (*Builder) WithJOSE added in v0.30.0

func (b *Builder) WithJOSE(cfg JOSEConfig) *Builder

WithJOSE configures a JOSETransport that signs+encrypts every outbound request body and decrypts+verifies application/jose response bodies. Pass cfg.Inbound = nil when the counterparty does not return JOSE-wrapped responses.

Composition: WithJOSE wraps whatever transport is currently configured (set by an earlier WithTransport or WithHTTPClient call) — so existing transport customizations remain in the chain below the JOSE layer. Calling WithTransport AFTER WithJOSE replaces the JOSE transport entirely.

Per-attempt freshness: because httpclient retries by re-running the request build loop, each retry produces a freshly-sealed payload — useful for protocols that require unique iat/jti claims per attempt.

func (*Builder) WithRequestInterceptor

func (b *Builder) WithRequestInterceptor(interceptor RequestInterceptor) *Builder

WithRequestInterceptor adds a request interceptor

func (*Builder) WithResponseInterceptor

func (b *Builder) WithResponseInterceptor(interceptor ResponseInterceptor) *Builder

WithResponseInterceptor adds a response interceptor

func (*Builder) WithRetries

func (b *Builder) WithRetries(maxRetries int, retryDelay time.Duration) *Builder

WithRetries sets the retry configuration

func (*Builder) WithTimeout

func (b *Builder) WithTimeout(timeout time.Duration) *Builder

WithTimeout sets the request timeout

func (*Builder) WithTraceIDExtractor

func (b *Builder) WithTraceIDExtractor(extractor func(_ context.Context) (string, bool)) *Builder

WithTraceIDExtractor sets a function to extract a trace ID from context

func (*Builder) WithTraceIDGenerator

func (b *Builder) WithTraceIDGenerator(gen func() string) *Builder

WithTraceIDGenerator sets the generator used when no trace ID is present

func (*Builder) WithTraceIDHeader

func (b *Builder) WithTraceIDHeader(name string) *Builder

WithTraceIDHeader sets the header name used for the trace ID (default: X-Request-ID)

func (*Builder) WithTransport

func (b *Builder) WithTransport(transport nethttp.RoundTripper) *Builder

WithTransport sets a custom RoundTripper while still letting the builder manage other client settings.

func (*Builder) WithW3CTrace

func (b *Builder) WithW3CTrace(enabled bool) *Builder

WithW3CTrace enables or disables W3C trace context propagation

type Client

type Client interface {
	Get(ctx context.Context, req *Request) (*Response, error)
	Post(ctx context.Context, req *Request) (*Response, error)
	Put(ctx context.Context, req *Request) (*Response, error)
	Patch(ctx context.Context, req *Request) (*Response, error)
	Delete(ctx context.Context, req *Request) (*Response, error)
	Do(ctx context.Context, method string, req *Request) (*Response, error)
}

Client defines the REST client interface for making HTTP requests

func NewClient

func NewClient(log logger.Logger) Client

NewClient creates a new REST client with default configuration

type ClientError

type ClientError interface {
	error
	Type() ErrorType
}

ClientError represents different types of REST client errors

func NewHTTPError

func NewHTTPError(message string, statusCode int, body []byte) ClientError

NewHTTPError creates a new HTTP error

func NewInterceptorError

func NewInterceptorError(message, stage string, wrapped error) ClientError

NewInterceptorError creates a new interceptor error

func NewNetworkError

func NewNetworkError(message string, wrapped error) ClientError

NewNetworkError creates a new network error

func NewTimeoutError

func NewTimeoutError(message string, timeout time.Duration) ClientError

NewTimeoutError creates a new timeout error

func NewValidationError

func NewValidationError(message, field string) ClientError

NewValidationError creates a new validation error

type Config

type Config struct {
	Timeout              time.Duration
	MaxRetries           int
	RetryDelay           time.Duration
	RequestInterceptors  []RequestInterceptor
	ResponseInterceptors []ResponseInterceptor
	BasicAuth            *BasicAuth
	DefaultHeaders       map[string]string
	// LogPayloads enables debug-level logging of headers and body payloads
	LogPayloads bool
	// MaxPayloadLogBytes caps the number of body bytes logged when LogPayloads is enabled
	MaxPayloadLogBytes int
	// TraceIDHeader configures the header name used for trace ID propagation (default: X-Request-ID)
	TraceIDHeader string
	// NewTraceID generates a new trace ID when none is present (default: uuid)
	NewTraceID func() string
	// TraceIDExtractor allows advanced extraction of a trace ID from context; return ok=false to fallback to generator
	TraceIDExtractor func(_ context.Context) (traceID string, ok bool)
	// EnableW3CTrace enables W3C Trace Context (traceparent/tracestate) propagation and generation
	EnableW3CTrace bool
}

Config holds the REST client configuration

type ErrorType

type ErrorType string

ErrorType defines the category of client error

const (
	NetworkError     ErrorType = "network"
	TimeoutError     ErrorType = "timeout"
	HTTPError        ErrorType = "http"
	ValidationError  ErrorType = "validation"
	InterceptorError ErrorType = "interceptor"
)

type JOSEConfig added in v0.30.0

type JOSEConfig struct {
	// Outbound is required: the policy used to sign+encrypt every outbound request body.
	Outbound *jose.Policy
	// Inbound is optional: when set, application/jose response bodies are decrypted+verified.
	// Plaintext responses (e.g., pre-trust error envelopes from the counterparty) pass
	// through unmodified.
	Inbound *jose.Policy
	// Resolver supplies keys for both Outbound and Inbound directions.
	Resolver jose.KeyResolver
}

JOSEConfig groups the JOSE policy and resolver passed to Builder.WithJOSE. A struct is used (rather than positional parameters) so future fields — clock override, replay-cache hook, per-call policy resolver — can be added without changing the WithJOSE signature.

type JOSETransport added in v0.30.0

type JOSETransport struct {
	// Inner is the underlying RoundTripper that performs the actual HTTP exchange.
	// Nil defaults to nethttp.DefaultTransport.
	Inner nethttp.RoundTripper

	// Outbound is required: the policy used to sign+encrypt every outbound request body.
	// A nil Outbound disables outbound wrapping entirely (the transport delegates to Inner).
	Outbound *jose.Policy

	// Inbound is optional: when set, application/jose responses are decrypted+verified.
	// Other response Content-Types pass through unmodified so plaintext error envelopes
	// from JOSE-aware counterparties (e.g., GoBricks pre-trust failures) remain readable.
	Inbound *jose.Policy

	// Resolver supplies keys for both Outbound (sign/encrypt) and Inbound (decrypt/verify).
	// Required when either policy is set.
	Resolver jose.KeyResolver

	// MaxResponseBytes bounds the response body read when Inbound is set. Zero means
	// use DefaultMaxJOSEBodyBytes. A negative value disables the cap entirely (NOT
	// recommended for untrusted counterparties).
	MaxResponseBytes int64
}

JOSETransport is an http.RoundTripper that signs+encrypts outbound request bodies (jose.Seal) and decrypts+verifies inbound response bodies (jose.Open) using a fixed pair of policies and a single KeyResolver.

Architectural placement: JOSETransport sits below the httpclient retry loop, so each retry attempt produces a freshly-sealed request — important for protocols that require unique iat/jti claims per attempt (Visa Token Services and similar).

Response Content-Type discrimination: only application/jose responses are unwrapped; other Content-Types pass through untouched. This mirrors the GoBricks server's hybrid error envelope — pre-trust failures from the counterparty come back as plaintext minimal JSON because the peer was never authenticated, and the transport must not attempt to decrypt those.

func (*JOSETransport) RoundTrip added in v0.30.0

func (t *JOSETransport) RoundTrip(req *nethttp.Request) (*nethttp.Response, error)

RoundTrip wraps the request body with JOSE (when Outbound is set), forwards to the inner transport, and unwraps the response body (when Inbound is set AND the response Content-Type matches application/jose).

type Request

type Request struct {
	URL     string
	Headers map[string]string
	Body    []byte
	Auth    *BasicAuth
}

Request represents an HTTP request with all necessary data

type RequestInterceptor

type RequestInterceptor func(ctx context.Context, req *nethttp.Request) error

RequestInterceptor is called before sending the request

func NewTraceIDInterceptor

func NewTraceIDInterceptor() RequestInterceptor

NewTraceIDInterceptor creates a request interceptor that adds trace ID headers This provides an alternative approach for users who want explicit control

func NewTraceIDInterceptorFor

func NewTraceIDInterceptorFor(header string) RequestInterceptor

NewTraceIDInterceptorFor creates an interceptor that uses a custom header name

type Response

type Response struct {
	StatusCode int
	Body       []byte
	Headers    nethttp.Header
	Stats      Stats
}

Response represents an HTTP response with tracking information

type ResponseInterceptor

type ResponseInterceptor func(ctx context.Context, req *nethttp.Request, resp *nethttp.Response) error

ResponseInterceptor is called after receiving the response

type Stats

type Stats struct {
	ElapsedTime time.Duration
	CallCount   int64
}

Stats contains request execution statistics

Jump to

Keyboard shortcuts

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