Documentation
¶
Index ¶
- Constants
- type APIError
- func (e *APIError) CatcherErrorID() string
- func (e *APIError) Error() string
- func (e *APIError) IsForbidden() bool
- func (e *APIError) IsNotFound() bool
- func (e *APIError) IsRateLimited() bool
- func (e *APIError) IsUnauthorized() bool
- func (e *APIError) IsValidationError() bool
- func (e *APIError) RetryAfter() string
- type Client
- type ListOptions
- type Option
- type SDKError
Constants ¶
const DefaultEndpoint = "https://api.threatwinds.com"
DefaultEndpoint is the default ThreatWinds API base URL.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type APIError ¶
type APIError struct {
StatusCode int `json:"status_code"`
Method string `json:"-"`
Path string `json:"-"`
Message string `json:"message"`
// ErrorID is the upstream's x-error-id response header exactly as
// received, unfiltered — this is a client-side type and the field means
// "what the server said". Whether that value is fit to become *this*
// process's occurrence id is a separate question, answered at the point of
// donation by CatcherErrorID rather than here, so that a caller inspecting
// the field still sees what actually came back.
ErrorID string `json:"error_id"`
Body []byte `json:"-"`
// contains filtered or unexported fields
}
APIError is returned when an API call results in a 4xx or 5xx response. It implements the error interface.
It is deliberately a plain error rather than a *catcher.SdkError: catcher.Error short-circuits when handed an *SdkError cause and returns it unchanged, discarding the wrapping call's message, args and status override. A caller that wraps this error therefore keeps its own framing, and inherits only the upstream's occurrence id, via CatcherErrorID below. See utils.RemoteError, which is the same decision for the same reason on the generic transport helper.
func (*APIError) CatcherErrorID ¶ added in v1.1.29
CatcherErrorID satisfies catcher.ErrorIDCarrier structurally — the interface is one method, and satisfying it requires declaring that method, not importing the package that declares the interface (see adoptErrorID for why this package imports nothing from the SDK). A caller wrapping this error with catcher.Error or catcher.New therefore builds its own error — its message, its args, its status — that nonetheless inherits this failure's occurrence id, rather than minting a second, unrelated id for one failure. The compile-time assertion that the interface is still the shape this method answers lives in error_test.go, where linking catcher costs nothing.
Without it the id read at client.doOnce went nowhere: APIError has no Unwrap, so catcher's errors.As walk found no carrier, and the id was not in Error()'s text either (it renders status, method, path and message only). catcher minted a fresh UUID, and the two services' log lines for one failure could no longer be correlated by id — the exact failure this interface exists to close.
The guard is applied here rather than when the header is read: ErrorID keeps its meaning of "what the server sent", while only the value that becomes an occurrence id in this process is required to be a canonical UUID. A malformed one is not donated — see adoptErrorID for why a remote-controlled id cannot be taken on trust.
It falls back to the id minted for this failure when the upstream supplied none the guard would accept, so the answer to "which occurrence is this?" is never empty and never changes between two wraps of the same error. The difference between the two cases is not lost — it is exactly what ErrorID reports — but it is not the wrapping caller's problem: either way this failure has one id, and the caller's error gets that one rather than a second.
Nil-safe: errors.As matches on type alone, so a typed-nil *APIError boxed in a non-nil error would otherwise reach this method on a nil receiver. catcher also guards that case, but a method reachable through an interface should not depend on its only caller being careful.
func (*APIError) Error ¶
Error renders the failure. It is nil-safe, and has to be now that this error is handed to catcher as a cause: catcher.build calls Error() on whatever cause it is given to fill Cause, and errors.As — which is how catcher finds this type — matches on type alone, so a typed-nil *APIError boxed in a non-nil error interface reaches this method on a nil receiver. That is the same trap catcher guards for *SdkError (see ToSdkError) and utils.RemoteError guards for itself, and it renders the same way: "<nil>".
func (*APIError) IsForbidden ¶
func (*APIError) IsNotFound ¶
The status predicates are nil-safe for the same reason Error is: the usual way a caller reaches one is errors.As, which sets its target from a type match and will happily hand back a nil pointer for a typed-nil in the chain. All of them answer false for a nil receiver — "this is not that kind of failure" — rather than panicking inside an `if err.IsNotFound()`.
func (*APIError) IsRateLimited ¶
func (*APIError) IsUnauthorized ¶
func (*APIError) IsValidationError ¶
func (*APIError) RetryAfter ¶
RetryAfter returns the Retry-After header value stored on the error, used by the retry logic to determine backoff duration.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is the root entry point for the ThreatWinds API SDK.
func New ¶
New creates a configured API client. At least one authentication option (WithAPIKey or WithBearer) must be provided, but not both.
func (*Client) Close ¶
func (c *Client) Close()
Close releases idle HTTP connections held by the SDK's internal transport. It is a no-op when the caller supplied their own http.Client via WithHTTPClient. Callers should invoke Close() when they are done with the client to avoid leaking TCP connections in long-running processes.
type ListOptions ¶
ListOptions holds pagination parameters for list endpoints.
type Option ¶
type Option func(*clientConfig)
Option configures a Client via the functional options pattern.
func WithAPIKey ¶
WithAPIKey sets API key authentication (key ID + secret).
func WithHTTPClient ¶
WithHTTPClient sets a custom HTTP client.
func WithMaxRetries ¶
WithMaxRetries sets the maximum number of retry attempts.
func WithTimeout ¶
WithTimeout sets the HTTP request timeout.
type SDKError ¶
type SDKError struct {
// contains filtered or unexported fields
}
SDKError is returned by New() for configuration errors (not HTTP errors).
It deliberately does not implement catcher.ErrorIDCarrier. It is raised before any request is made — a missing or conflicting authentication option — so there is no upstream, no x-error-id, and nothing to adopt. A caller wrapping it with catcher gets a freshly minted id, which is the correct outcome for a failure that originated in this process: implementing the interface to return "" would be indistinguishable in behaviour and would falsely advertise that this error type participates in cross-service propagation.