Documentation
¶
Overview ¶
Package http provides an HTTP client wrapper for the MarketData SDK.
Index ¶
- Constants
- func PathSegment(s string) string
- func Version() string
- type Client
- func (c *Client) CloseIdleConnections()
- func (c *Client) Do(ctx context.Context, req Request) (*Response, error)
- func (c *Client) Get(ctx context.Context, path string, params url.Values, result any) (*Response, error)
- func (c *Client) GetFormatted(ctx context.Context, path string, params url.Values, format string) (*Response, error)
- func (c *Client) GetUnversioned(ctx context.Context, path string, params url.Values, result any) (*Response, error)
- func (c *Client) GetUnversionedSilent(ctx context.Context, path string, params url.Values, result any) (*Response, error)
- func (c *Client) SetDebug(enabled bool)
- func (c *Client) StatusProbe(ctx context.Context) (bool, error)
- type ColumnRequirer
- type Config
- type Request
- type Response
Constants ¶
const DefaultPoolSize = 50
DefaultPoolSize is the SDK's global concurrency pool size (ADR-014): NewClient's semaphore channel is sized to this, and this same constant backs the pool-saturation test, so a change to one is a change to both — a test asserting the wrong number silently (see T-5 in the deep review) can no longer happen.
Variables ¶
This section is empty.
Functions ¶
func PathSegment ¶
PathSegment percent-encodes a caller-supplied value for safe use as a single URL path segment. It prevents path injection: a value such as "AAPL/../user" cannot escape its segment or re-route the request. Dot-segments ("." and ".."), which percent-encoding leaves intact because dots are unreserved, are neutralized explicitly.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client wraps http.Client with SDK-specific functionality.
func (*Client) CloseIdleConnections ¶
func (c *Client) CloseIdleConnections()
CloseIdleConnections closes any idle HTTP connections on the transport the SDK built for itself. It is a no-op when the underlying *http.Client was supplied via WithHTTPClient: that transport (and its connection pool) is intentionally shared with the caller, so closing its idle connections here would reach outside the SDK and affect the caller's own in-flight or pooled requests on that same client.
func (*Client) Get ¶
func (c *Client) Get(ctx context.Context, path string, params url.Values, result any) (*Response, error)
Get executes a GET request and decodes the JSON response, logging any terminal failure at ERROR (see logTerminalFailure).
func (*Client) GetFormatted ¶
func (c *Client) GetFormatted(ctx context.Context, path string, params url.Values, format string) (*Response, error)
GetFormatted executes a GET request asking for a non-JSON wire format (format=csv or format=html, see ADR-018) and returns the raw response body as-is — no JSON decoding. Logs any terminal failure at ERROR (see logTerminalFailure), same as Get.
Unlike Get, this has no NoData concept: the API's own "no data" body shape is not consistent between JSON (404, a typed no-data body) and these formats (verified live: the same no-data condition on a CSV-formatted candles request comes back 200 with a degenerate body, not 404) — so 404/204 are passed through like any other status rather than specially interpreted. The caller gets whatever text came back.
func (*Client) GetUnversioned ¶
func (c *Client) GetUnversioned(ctx context.Context, path string, params url.Values, result any) (*Response, error)
GetUnversioned executes a GET request without API version prefix. Used for endpoints like /status/ that are not versioned. Logs any terminal failure at ERROR (see logTerminalFailure).
func (*Client) GetUnversionedSilent ¶
func (c *Client) GetUnversionedSilent(ctx context.Context, path string, params url.Values, result any) (*Response, error)
GetUnversionedSilent is [GetUnversioned] without the ERROR log on failure. Reserved for best-effort background priming (rate-limit state at startup) whose caller already discards the error by design — logging it there would either be pure noise or duplicate an ERROR already logged by a synchronous call to the same endpoint moments earlier.
func (*Client) SetDebug ¶
SetDebug enables or disables emission of per-request debug records at runtime. It is safe for concurrent use with in-flight requests.
func (*Client) StatusProbe ¶
StatusProbe issues a minimal direct GET against the unversioned /status/ endpoint and reports whether the API answered as online (200 or 203). It deliberately bypasses the concurrency pool, retry loop, and rate-limit accounting: the offline-gate's background probe must stay responsive precisely when the pool is saturated or requests are failing, and must not pollute credit accounting.
type ColumnRequirer ¶
type ColumnRequirer interface {
RequiredColumns() []string
}
ColumnRequirer is implemented by a wire-response type whose decode needs a column the caller's "columns" filter may have dropped.
The rule is narrow on purpose. WithColumns promises that "missing columns simply decode as zero values", and for a data field that is exactly what happens — a filtered-out bid reads as 0. One column per response type is different: the array the conversion takes its row count from. Drop that one and every row disappears, so a present, billed quote is reported as not found. That is not a zero value, it is a wrong answer, and it is the same failure mode as the dropped "s" envelope — a field the decoder needs and the caller never thought to ask for.
Implementations return nil when they have no such column. Every wire response type implements it, which TestEveryWireResponseDeclaresRequiredColumns enforces as new ones are added.
type Config ¶
type Config struct {
HTTPClient *http.Client
BaseURL string
APIVersion string
Token string
Timeout time.Duration
ConnTimeout time.Duration
RetryCfg retry.Config
RateLimits *ratelimit.Tracker
Logger *slog.Logger
Debug bool
DemoMode bool
Sem chan struct{}
DefaultParams url.Values
FormatOnlyParams url.Values // universal default params (from env vars / client config)
StatusCache *status.Cache // API status cache for retry decisions
MaxRespBytes int64 // cap on response body size (0 = default)
}
Config holds the HTTP client configuration.
type Request ¶
type Request struct {
Method string
Path string
Params url.Values
Headers map[string]string
Unversioned bool // If true, don't prefix with API version
// RawFormat marks a request whose body is handed back verbatim (the
// CSV/HTML facets, see ADR-018) rather than decoded. It exists so
// decoder-serving adjustments — the "columns" repair below — apply only
// where something actually decodes.
RawFormat bool
// RequiredColumns names the response columns this request's decoder
// cannot do without, on top of the "s" envelope. Get fills it from the
// destination value; see ColumnRequirer.
RequiredColumns []string
}
Request represents an API request.
type Response ¶
type Response struct {
Raw *http.Response // the raw HTTP response (body already consumed)
StatusCode int
Headers http.Header
Body []byte
RequestID string
}
Response represents an API response.
func (*Response) StatusError ¶
StatusError builds the sdkerrors.APIError every service raises when a 200 response carries a body whose own "s" field is not "ok" — the one failure mode the >=400 mapping in parseAPIError cannot see. Every such guard is identical apart from the status string, so they share this method rather than repeating the same SupportContext call at each of the service call sites. A guard that genuinely needs a different exception type still calls Response.SupportContext directly.
func (*Response) SupportContext ¶
func (r *Response) SupportContext(message, exceptionType string) sdkerrors.SupportContext
SupportContext builds a sdkerrors.SupportContext for an error tied to this response, filling RequestID, RequestURL, StatusCode, and Timestamp from the response itself so callers only need to supply the message and exception type. Used for errors raised outside the >=400 status mapping in parseAPIError — e.g. an HTTP 200 whose body reports its own failure.
RequestURL goes through wireURL like the >=400 and ParseError blocks do. It used to report Raw.Request.URL.Path, so all fifteen StatusError sites produced a support block stripped of the query — and Quote is served by bulkquotes, which addresses by query, so the block for a failed Quote(ctx, "AAPL") did not even say which symbol was asked for. A block exists to be pasted into a ticket, and this is the error class where the merged universal parameters matter most: a 200 whose body reports its own failure is the one most likely to have been caused by them.