Documentation
¶
Index ¶
- Constants
- func EnsureTraceID(ctx context.Context) string
- func GenerateTraceParent() string
- func IsErrorType(err error, errorType ErrorType) bool
- func IsHTTPStatusError(err error, statusCode int) bool
- func IsJOSEError(err error) bool
- func IsSuccessStatus(statusCode int) bool
- func TraceIDFromContext(ctx context.Context) (string, bool)
- func TraceParentFromContext(ctx context.Context) (string, bool)
- func TraceStateFromContext(ctx context.Context) (string, bool)
- func WithTraceID(ctx context.Context, traceID string) context.Context
- func WithTraceParent(ctx context.Context, traceParent string) context.Context
- func WithTraceState(ctx context.Context, traceState string) context.Context
- type BasicAuth
- type Builder
- func (b *Builder) Build() Client
- func (b *Builder) WithBasicAuth(username, password string) *Builder
- func (b *Builder) WithDefaultHeader(key, value string) *Builder
- func (b *Builder) WithHTTPClient(client *nethttp.Client) *Builder
- func (b *Builder) WithJOSE(cfg JOSEConfig) *Builder
- func (b *Builder) WithRequestInterceptor(interceptor RequestInterceptor) *Builder
- func (b *Builder) WithResponseInterceptor(interceptor ResponseInterceptor) *Builder
- func (b *Builder) WithRetries(maxRetries int, retryDelay time.Duration) *Builder
- func (b *Builder) WithTimeout(timeout time.Duration) *Builder
- func (b *Builder) WithTraceIDExtractor(extractor func(_ context.Context) (string, bool)) *Builder
- func (b *Builder) WithTraceIDGenerator(gen func() string) *Builder
- func (b *Builder) WithTraceIDHeader(name string) *Builder
- func (b *Builder) WithTransport(transport nethttp.RoundTripper) *Builder
- func (b *Builder) WithW3CTrace(enabled bool) *Builder
- type Client
- type ClientError
- func NewHTTPError(message string, statusCode int, body []byte) ClientError
- func NewInterceptorError(message, stage string, wrapped error) ClientError
- func NewNetworkError(message string, wrapped error) ClientError
- func NewTimeoutError(message string, timeout time.Duration) ClientError
- func NewValidationError(message, field string) ClientError
- type Config
- type ErrorType
- type JOSEConfig
- type JOSETransport
- type Request
- type RequestInterceptor
- type Response
- type ResponseInterceptor
- type Stats
Constants ¶
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 )
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 )
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 ¶
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 ¶
IsErrorType checks if an error is of a specific type
func IsHTTPStatusError ¶
IsHTTPStatusError checks if an error is an HTTP error with a specific status code
func IsJOSEError ¶ added in v0.30.0
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 ¶
IsSuccessStatus checks if a status code represents success (2xx)
func TraceIDFromContext ¶
TraceIDFromContext returns a trace ID from context if present
func TraceParentFromContext ¶
TraceParentFromContext returns a traceparent from context if present
func TraceStateFromContext ¶
TraceStateFromContext returns a tracestate from context if present
func WithTraceID ¶
WithTraceID adds a trace ID to the context for HTTP client propagation
func WithTraceParent ¶
WithTraceParent adds a W3C traceparent value to the context
Types ¶
type Builder ¶
type Builder struct {
// contains filtered or unexported fields
}
Builder provides a fluent interface for configuring the REST client
func NewBuilder ¶
NewBuilder creates a new client builder
func (*Builder) WithBasicAuth ¶
WithBasicAuth sets basic authentication credentials
func (*Builder) WithDefaultHeader ¶
WithDefaultHeader adds a default header that will be sent with all requests
func (*Builder) WithHTTPClient ¶
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 ¶
WithRetries sets the retry configuration
func (*Builder) WithTimeout ¶
WithTimeout sets the request timeout
func (*Builder) WithTraceIDExtractor ¶
WithTraceIDExtractor sets a function to extract a trace ID from context
func (*Builder) WithTraceIDGenerator ¶
WithTraceIDGenerator sets the generator used when no trace ID is present
func (*Builder) WithTraceIDHeader ¶
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 ¶
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
type ClientError ¶
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 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.
type RequestInterceptor ¶
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