Documentation
¶
Index ¶
- Constants
- func ClassifyNetworkError(err error) string
- func IsProxyInfraError(err error) bool
- func MapEnvoyResponseFlag(flag string) string
- func ParseHTTPResponse(delivery *destregistry.Delivery, resp *http.Response, maxBytes int)
- func ValidateCustomHeaders(headers map[string]string) error
- func WrapTransport(transport *http.Transport, proxyURL *url.URL) http.RoundTripper
- type Base64Encoder
- type ErrProxyDestination
- type ErrProxyInfra
- type HTTPRequestResult
- type HeaderFormatter
- type HeaderFormatterImpl
- type HeaderPayload
- type HexEncoder
- type HmacAlgo
- type Option
- func WithConnectionObserver(fn func(reused bool)) Option
- func WithConnectionPool(pool destregistry.PoolSizing) Option
- func WithEventIDHeader(name string, disabled bool) Option
- func WithHeaderPrefix(prefix string) Option
- func WithMaxResponseBodyBytes(maxBytes int) Option
- func WithProxy(hops []*url.URL) Option
- func WithSignatureAlgorithm(algorithm string) Option
- func WithSignatureContentTemplate(template string) Option
- func WithSignatureEncoding(encoding string) Option
- func WithSignatureHeader(name string, disabled bool) Option
- func WithSignatureHeaderTemplate(template string) Option
- func WithSigningSecretTemplate(templateStr string) Option
- func WithTimestampHeader(name string, disabled bool) Option
- func WithTopicHeader(name string, disabled bool) Option
- func WithUserAgent(userAgent string) Option
- type SignatureEncoder
- type SignatureFormatter
- type SignatureFormatterImpl
- type SignatureManager
- type SignatureManagerOption
- type SignaturePayload
- type SigningAlgorithm
- type WebhookDestination
- func (d *WebhookDestination) ComputeTarget(destination *models.Destination) destregistry.DestinationTarget
- func (d *WebhookDestination) CreatePublisher(ctx context.Context, destination *models.Destination) (destregistry.Publisher, error)
- func (d *WebhookDestination) GetSignatureAlgorithm() string
- func (d *WebhookDestination) GetSignatureEncoding() string
- func (d *WebhookDestination) ObfuscateDestination(destination *models.Destination) *models.Destination
- func (d *WebhookDestination) Preprocess(newDestination *models.Destination, originalDestination *models.Destination, ...) error
- func (d *WebhookDestination) Validate(ctx context.Context, destination *models.Destination) error
- type WebhookDestinationConfig
- type WebhookDestinationCredentials
- type WebhookPublisher
- type WebhookSecret
Constants ¶
const ( DefaultEncoding = "hex" DefaultAlgorithm = "hmac-sha256" DefaultHeaderPrefix = "x-outpost-" DefaultSignatureContentTmpl = "{{.Body}}" DefaultSignatureHeaderTmpl = "v0={{.Signatures | join \",\"}}" DefaultSigningSecretTmpl = "whsec_{{.RandomHex}}" )
Variables ¶
This section is empty.
Functions ¶
func ClassifyNetworkError ¶ added in v0.11.0
ClassifyNetworkError returns a descriptive error code based on the error type. All errors classified here are destination-level failures (DeliveryError → ack + retry).
Error codes and their meanings:
- dns_error: Domain doesn't exist or DNS lookup failed
- connection_refused: Server not running or rejecting connections
- connection_reset: Connection was dropped by the server
- network_unreachable: Network path to destination is unavailable
- timeout: Request took too long (I/O timeout or context deadline)
- tls_error: TLS/SSL certificate or handshake failure
- redirect_error: Too many redirects
- network_error: Other network-related failures (catch-all)
func IsProxyInfraError ¶ added in v1.0.3
IsProxyInfraError reports whether err is or wraps an ErrProxyInfra.
func MapEnvoyResponseFlag ¶ added in v1.0.3
MapEnvoyResponseFlag returns the destination error code corresponding to an Envoy response flag. The output vocabulary matches ClassifyNetworkError (httphelper.go) so customers see the same codes whether or not a proxy is in path. Unhandled flags fall through to "network_error" — operators should watch for that code paired with a non-empty flag in the attempt error payload as a signal that the mapping needs expansion.
Envoy response flag reference: https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#config-access-log-format-response-flags
func ParseHTTPResponse ¶ added in v0.11.0
func ParseHTTPResponse(delivery *destregistry.Delivery, resp *http.Response, maxBytes int)
ParseHTTPResponse reads the HTTP response body into the delivery as a raw string. The body is stored verbatim regardless of content type to preserve data integrity.
maxBytes caps the stored body so an oversized response can't push the attempt log past the queue's per-message size limit (which would fail to publish and retry forever). 0 disables the cap. When the body exceeds maxBytes it is replaced wholesale with a placeholder rather than truncated, so consumers never receive a partial/corrupt body. We read with a maxBytes+1 LimitReader: enough to detect the overflow without buffering the whole body, but it means we stop before draining resp.Body, so that connection won't be reused — an acceptable trade-off versus downloading an arbitrarily large body just to discard it.
func ValidateCustomHeaders ¶ added in v0.10.0
ValidateCustomHeaders validates custom header names and values
func WrapTransport ¶ added in v1.0.3
WrapTransport is the destregistry.HTTPClientConfig.WrapTransport hook for webhook destinations. It installs OnProxyConnectResponse on the underlying transport and wraps it in proxyTransport so request- and response-time proxy failures get translated into ErrProxyInfra / ErrProxyDestination.
Types ¶
type Base64Encoder ¶
type Base64Encoder struct{}
func (Base64Encoder) Encode ¶
func (e Base64Encoder) Encode(b []byte) string
type ErrProxyDestination ¶ added in v1.0.3
type ErrProxyDestination struct {
Underlying error
Code string
DestHost string
Diagnostics map[string]string
}
ErrProxyDestination signals that the proxy reported a failure originating at the destination (e.g. upstream DNS lookup failed, upstream connection refused, upstream timeout). The delivery result is recorded as a normal failed attempt using Code as the classification, with response data rewritten so the customer sees a destination-attributed failure rather than proxy-attributed details.
Diagnostics is a free-form key/value map of proxy-specific signals the classification path picked up (e.g. for Envoy, "envoy_flag" and "envoy_details"). It is operator-side metadata only: surfaced in error logs and on the publish-attempt error payload, never written to the customer-visible attempt record. Whichever proxy emitted the data owns the key naming so heterogeneous proxies can coexist without colliding.
func (*ErrProxyDestination) Error ¶ added in v1.0.3
func (e *ErrProxyDestination) Error() string
func (*ErrProxyDestination) Unwrap ¶ added in v1.0.3
func (e *ErrProxyDestination) Unwrap() error
type ErrProxyInfra ¶ added in v1.0.3
ErrProxyInfra signals that a webhook delivery failed at the proxy layer (proxy auth misconfiguration, proxy unreachable, etc.). The delivery result is nacked so the underlying message queue redelivers without recording a customer-visible failed attempt.
func (*ErrProxyInfra) Error ¶ added in v1.0.3
func (e *ErrProxyInfra) Error() string
func (*ErrProxyInfra) Unwrap ¶ added in v1.0.3
func (e *ErrProxyInfra) Unwrap() error
type HTTPRequestResult ¶ added in v0.11.0
type HTTPRequestResult struct {
// Delivery is the delivery result.
Delivery *destregistry.Delivery
// Error is the error that occurred, if any.
Error error
// Response is the HTTP response, if one was received. Caller should NOT close the body.
Response *http.Response
}
HTTPRequestResult contains the result of an HTTP request execution.
func ExecuteHTTPRequest ¶ added in v0.11.0
func ExecuteHTTPRequest(ctx context.Context, client *http.Client, req *http.Request, provider string, maxResponseBodyBytes int) *HTTPRequestResult
ExecuteHTTPRequest executes an HTTP request and classifies the result.
Most errors return a Delivery object with a classified error code so the caller can record a failed attempt.
Proxy *infrastructure* errors (ErrProxyInfra) return Delivery: nil so the caller signals the queue to nack the message instead of recording a customer-visible attempt. See registry.go for the nil-attempt handling.
maxResponseBodyBytes caps how much of the destination response body is read and stored on the attempt. 0 means no limit. See ParseHTTPResponse.
type HeaderFormatter ¶
type HeaderFormatter interface {
Format(content HeaderPayload) (string, error)
}
type HeaderFormatterImpl ¶
type HeaderFormatterImpl struct {
// contains filtered or unexported fields
}
func NewHeaderFormatter ¶
func NewHeaderFormatter(templateStr string) (*HeaderFormatterImpl, error)
func (*HeaderFormatterImpl) Format ¶
func (f *HeaderFormatterImpl) Format(content HeaderPayload) (string, error)
Format renders the header template. See SignatureFormatterImpl.Format for why execution errors are returned rather than fatal.
type HeaderPayload ¶
type HexEncoder ¶
type HexEncoder struct{}
func (HexEncoder) Encode ¶
func (e HexEncoder) Encode(b []byte) string
type HmacAlgo ¶
type HmacAlgo struct {
// contains filtered or unexported fields
}
func NewHmacMD5 ¶
func NewHmacMD5() *HmacAlgo
func NewHmacSHA1 ¶
func NewHmacSHA1() *HmacAlgo
func NewHmacSHA256 ¶
func NewHmacSHA256() *HmacAlgo
type Option ¶
type Option func(*WebhookDestination)
Option is a functional option for configuring WebhookDestination
func WithConnectionObserver ¶ added in v1.2.0
WithConnectionObserver registers a callback invoked once per request with whether the underlying connection was reused.
func WithConnectionPool ¶ added in v1.2.0
func WithConnectionPool(pool destregistry.PoolSizing) Option
WithConnectionPool sizes the shared client's idle connection pool. The zero value leaves Go's defaults in place.
func WithEventIDHeader ¶ added in v1.1.0
WithEventIDHeader sets the event ID header directive. A non-empty name pins the exact header name (bypassing "<prefix>event-id"); disabled omits the header. The name is trimmed of whitespace.
func WithHeaderPrefix ¶
WithHeaderPrefix sets the prefix for webhook request headers. The prefix is trimmed of whitespace. An empty string disables the prefix entirely. Config is responsible for providing the appropriate default ("x-outpost-" or "webhook-").
func WithMaxResponseBodyBytes ¶ added in v1.1.0
WithMaxResponseBodyBytes caps how much of the destination response body is stored on the attempt. 0 (default) disables the cap.
func WithProxy ¶ added in v1.3.0
WithProxy routes every request through the given forward proxies, nearest hop first. See destregistry.ParseProxyURL.
func WithSignatureAlgorithm ¶
func WithSignatureEncoding ¶
func WithSignatureHeader ¶ added in v1.1.0
WithSignatureHeader sets the signature header directive. A non-empty name pins the exact header name (bypassing "<prefix>signature"); disabled omits the header. The name is trimmed of whitespace.
func WithSigningSecretTemplate ¶ added in v0.16.0
func WithTimestampHeader ¶ added in v1.1.0
WithTimestampHeader sets the timestamp header directive. A non-empty name pins the exact header name (bypassing "<prefix>timestamp"); disabled omits the header. The name is trimmed of whitespace.
func WithTopicHeader ¶ added in v1.1.0
WithTopicHeader sets the topic header directive. A non-empty name pins the exact header name (bypassing "<prefix>topic"); disabled omits the header. The name is trimmed of whitespace.
func WithUserAgent ¶
WithUserAgent sets the user agent for the webhook request
type SignatureEncoder ¶
func GetEncoder ¶
func GetEncoder(encoding string) SignatureEncoder
GetEncoder returns the appropriate SignatureEncoder for the given encoding
type SignatureFormatter ¶
type SignatureFormatter interface {
Format(content SignaturePayload) (string, error)
}
type SignatureFormatterImpl ¶
type SignatureFormatterImpl struct {
// contains filtered or unexported fields
}
func NewSignatureFormatter ¶
func NewSignatureFormatter(templateStr string) (*SignatureFormatterImpl, error)
func (*SignatureFormatterImpl) Format ¶
func (f *SignatureFormatterImpl) Format(content SignaturePayload) (string, error)
Format renders the content template. Parsing only validates syntax; field references are resolved against the payload at execution, so a template that constructs fine can still fail here. The error is returned so the caller can fail the delivery instead of taking the process down.
type SignatureManager ¶
type SignatureManager struct {
// contains filtered or unexported fields
}
func NewSignatureManager ¶
func NewSignatureManager(secrets []WebhookSecret, opts ...SignatureManagerOption) *SignatureManager
func (*SignatureManager) GenerateSignatureHeader ¶
func (sm *SignatureManager) GenerateSignatureHeader(content SignaturePayload) (string, error)
func (*SignatureManager) GenerateSignatures ¶
func (sm *SignatureManager) GenerateSignatures(content SignaturePayload) ([]string, error)
func (*SignatureManager) VerifySignature ¶
func (sm *SignatureManager) VerifySignature(signature, key string, content SignaturePayload) bool
VerifySignature reports whether signature matches key. It returns false when the content template fails to render, since no signature can be verified.
type SignatureManagerOption ¶
type SignatureManagerOption func(*SignatureManager)
func WithAlgorithm ¶
func WithAlgorithm(algo SigningAlgorithm) SignatureManagerOption
func WithEncoder ¶
func WithEncoder(encoder SignatureEncoder) SignatureManagerOption
func WithHeaderFormatter ¶
func WithHeaderFormatter(formatter HeaderFormatter) SignatureManagerOption
func WithSignatureFormatter ¶
func WithSignatureFormatter(formatter SignatureFormatter) SignatureManagerOption
type SignaturePayload ¶
type SigningAlgorithm ¶
type SigningAlgorithm interface {
Sign(key string, content string, encoder SignatureEncoder) string
Verify(key string, content string, signature string, encoder SignatureEncoder) bool
Name() string
}
func GetAlgorithm ¶
func GetAlgorithm(algorithm string) SigningAlgorithm
GetAlgorithm returns the appropriate SigningAlgorithm for the given algorithm name
type WebhookDestination ¶
type WebhookDestination struct {
*destregistry.BaseProvider
// contains filtered or unexported fields
}
func New ¶
func New(loader metadata.MetadataLoader, basePublisherOpts []destregistry.BasePublisherOption, opts ...Option) (*WebhookDestination, error)
func (*WebhookDestination) ComputeTarget ¶
func (d *WebhookDestination) ComputeTarget(destination *models.Destination) destregistry.DestinationTarget
func (*WebhookDestination) CreatePublisher ¶
func (d *WebhookDestination) CreatePublisher(ctx context.Context, destination *models.Destination) (destregistry.Publisher, error)
func (*WebhookDestination) GetSignatureAlgorithm ¶
func (d *WebhookDestination) GetSignatureAlgorithm() string
func (*WebhookDestination) GetSignatureEncoding ¶
func (d *WebhookDestination) GetSignatureEncoding() string
func (*WebhookDestination) ObfuscateDestination ¶
func (d *WebhookDestination) ObfuscateDestination(destination *models.Destination) *models.Destination
ObfuscateDestination overrides the base implementation to handle webhook secrets
func (*WebhookDestination) Preprocess ¶
func (d *WebhookDestination) Preprocess(newDestination *models.Destination, originalDestination *models.Destination, opts *destregistry.PreprocessDestinationOpts) error
Preprocess sets a default secret if one isn't provided and handles secret rotation
func (*WebhookDestination) Validate ¶
func (d *WebhookDestination) Validate(ctx context.Context, destination *models.Destination) error
type WebhookPublisher ¶
type WebhookPublisher struct {
*destregistry.BasePublisher
// contains filtered or unexported fields
}
func (*WebhookPublisher) Close ¶
func (p *WebhookPublisher) Close() error
func (*WebhookPublisher) Format ¶
Format is a helper function to format the event data into an HTTP request.
func (*WebhookPublisher) Publish ¶
func (p *WebhookPublisher) Publish(ctx context.Context, event *models.Event) (*destregistry.Delivery, error)