destwebhook

package
v1.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 9, 2026 License: Apache-2.0 Imports: 27 Imported by: 0

Documentation

Index

Constants

View Source
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

func ClassifyNetworkError(err error) string

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

func IsProxyInfraError(err error) bool

IsProxyInfraError reports whether err is or wraps an ErrProxyInfra.

func MapEnvoyResponseFlag added in v1.0.3

func MapEnvoyResponseFlag(flag string) string

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

func ValidateCustomHeaders(headers map[string]string) error

ValidateCustomHeaders validates custom header names and values

func WrapTransport added in v1.0.3

func WrapTransport(transport *http.Transport, proxyURL *url.URL) http.RoundTripper

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

type ErrProxyInfra struct {
	Underlying error
	DestHost   string
}

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.

See: https://github.com/hookdeck/outpost/issues/571

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 HeaderPayload struct {
	EventID    string
	Topic      string
	Timestamp  time.Time
	Signatures []string
}

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

func (*HmacAlgo) Name

func (h *HmacAlgo) Name() string

func (*HmacAlgo) Sign

func (h *HmacAlgo) Sign(key string, content string, encoder SignatureEncoder) string

func (*HmacAlgo) Verify

func (h *HmacAlgo) Verify(key string, content string, signature string, encoder SignatureEncoder) bool

type Option

type Option func(*WebhookDestination)

Option is a functional option for configuring WebhookDestination

func WithConnectionObserver added in v1.2.0

func WithConnectionObserver(fn func(reused bool)) Option

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

func WithEventIDHeader(name string, disabled bool) Option

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

func WithHeaderPrefix(prefix string) Option

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

func WithMaxResponseBodyBytes(maxBytes int) Option

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

func WithProxy(hops []*url.URL) Option

WithProxy routes every request through the given forward proxies, nearest hop first. See destregistry.ParseProxyURL.

func WithSignatureAlgorithm

func WithSignatureAlgorithm(algorithm string) Option

func WithSignatureContentTemplate

func WithSignatureContentTemplate(template string) Option

func WithSignatureEncoding

func WithSignatureEncoding(encoding string) Option

func WithSignatureHeader added in v1.1.0

func WithSignatureHeader(name string, disabled bool) Option

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 WithSignatureHeaderTemplate

func WithSignatureHeaderTemplate(template string) Option

func WithSigningSecretTemplate added in v0.16.0

func WithSigningSecretTemplate(templateStr string) Option

func WithTimestampHeader added in v1.1.0

func WithTimestampHeader(name string, disabled bool) Option

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

func WithTopicHeader(name string, disabled bool) Option

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

func WithUserAgent(userAgent string) Option

WithUserAgent sets the user agent for the webhook request

type SignatureEncoder

type SignatureEncoder interface {
	Encode([]byte) string
}

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 WithEncoder

func WithEncoder(encoder SignatureEncoder) SignatureManagerOption

func WithHeaderFormatter

func WithHeaderFormatter(formatter HeaderFormatter) SignatureManagerOption

func WithSignatureFormatter

func WithSignatureFormatter(formatter SignatureFormatter) SignatureManagerOption

type SignaturePayload

type SignaturePayload struct {
	EventID   string
	Topic     string
	Timestamp time.Time
	Body      string
}

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 WebhookDestinationConfig

type WebhookDestinationConfig struct {
	URL           string
	CustomHeaders map[string]string
}

type WebhookDestinationCredentials

type WebhookDestinationCredentials struct {
	Secret                  string    `json:"secret"`
	PreviousSecret          string    `json:"previous_secret,omitempty"`
	PreviousSecretInvalidAt time.Time `json:"previous_secret_invalid_at,omitempty"`
}

type WebhookPublisher

type WebhookPublisher struct {
	*destregistry.BasePublisher
	// contains filtered or unexported fields
}

func (*WebhookPublisher) Close

func (p *WebhookPublisher) Close() error

func (*WebhookPublisher) Format

func (p *WebhookPublisher) Format(ctx context.Context, event *models.Event) (*http.Request, error)

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)

type WebhookSecret

type WebhookSecret struct {
	Key       string     `json:"key"`
	CreatedAt time.Time  `json:"created_at"`
	InvalidAt *time.Time `json:"invalid_at,omitempty"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL