Skip to content

Transport

Transport is the thin HTTP layer every domain package’s calling function uses to send a HeaderBuilder-built request and decode its response.

Transport

type Transport struct {
	HTTPClient *http.Client
}
func (t *Transport) Do(ctx context.Context, hb HeaderBuilder) (Envelope, error)

Do signs hb (via hb.Build()), sends it, and decodes the response body into an Envelope. It does not retry, rate-limit, or interpret a non-2xx responseCode as a Go error — only transport-level failures (header-build error, network error, non-JSON body, context cancellation) come back as error. Interpreting a decoded response as success/failure is the caller’s job, via snap.CheckResponseStatus (see Errors).

When HTTPClient is left nil, Transport builds one with a default timeout that never follows redirects. This matters: Go’s default HTTP client forwards most headers (including your signed X-SIGNATURE, X-CLIENT-KEY, X-PARTNER-ID) — and, for a 307/308, the full body — to whatever host a redirect points at. No SNAP endpoint has a legitimate reason to redirect, so Do treats one like any other failed request instead of following it.

Response bodies are capped at a fixed size while reading, so a misbehaving or malicious server can’t force unbounded memory use.

Envelope

type Envelope struct {
	StatusCode      int
	ResponseCode    string
	ResponseMessage string
	Raw             json.RawMessage
}

Envelope is the generic decoded response: the transport-level HTTP StatusCode plus whatever SNAP envelope fields the body carried. Each domain package’s calling function unmarshals Raw into its own typed response.

StatusCode matters because ResponseCode is only reliable when the server actually returned SNAP’s own error shape — a body from a proxy, WAF, or gateway in front of it may carry no ResponseCode at all. A binding with no ResponseCode to fall back on should key off StatusCode instead, the same pattern TokenManager uses internally.

Next