Jido.Signal.Dispatch.Webhook (Jido v1.1.0-rc.2)

View Source

An adapter for dispatching signals to webhooks.

This adapter implements the Jido.Signal.Dispatch.Adapter behaviour and extends the HTTP adapter with webhook-specific functionality. It provides features like:

  • Signature generation for webhook payloads
  • Standard webhook headers
  • Webhook-specific retry policies
  • Event type mapping

Configuration Options

  • :url - (required) The webhook URL to send the request to
  • :secret - (optional) Secret key for generating signatures
  • :signature_header - (optional) Header name for the signature, defaults to "x-webhook-signature"
  • :event_type_header - (optional) Header name for the event type, defaults to "x-webhook-event"
  • :event_type_map - (optional) Map of signal types to webhook event types
  • All other options from Jido.Signal.Dispatch.Http

Examples

# Basic webhook with signature
config = {:webhook, [
  url: "https://api.example.com/webhook",
  secret: "webhook_secret"
]}

# Advanced configuration
config = {:webhook, [
  url: "https://api.example.com/webhook",
  secret: "webhook_secret",
  signature_header: "x-signature",
  event_type_header: "x-event-type",
  event_type_map: %{
    "user:created" => "user.created",
    "user:updated" => "user.updated"
  },
  timeout: 10_000,
  retry: %{
    max_attempts: 5,
    base_delay: 2000,
    max_delay: 10000
  }
]}

Webhook Signatures

When a secret is provided, the adapter will:

  1. Generate a signature of the payload using HMAC-SHA256
  2. Add the signature to the request headers
  3. Include a timestamp to prevent replay attacks

Event Type Mapping

The adapter can map internal signal types to external webhook event types:

event_type_map = %{
  "user:created" => "user.created",
  "user:updated" => "user.updated"
}

If no mapping is provided, the original signal type is used.

Error Handling

In addition to HTTP adapter errors, this adapter handles:

  • :invalid_secret - Secret key is not valid
  • :invalid_event_type_map - Event type mapping is invalid

Summary

Functions

Delivers a signal via webhook.

Validates the webhook adapter configuration options.

Types

webhook_error()

@type webhook_error() ::
  :invalid_secret
  | :invalid_event_type_map
  | Jido.Signal.Dispatch.Http.delivery_error()

webhook_opts()

@type webhook_opts() :: [
  url: String.t(),
  secret: String.t() | nil,
  signature_header: String.t(),
  event_type_header: String.t(),
  event_type_map: %{required(String.t()) => String.t()} | nil
]

Functions

deliver(signal, opts)

@spec deliver(Jido.Signal.t(), webhook_opts()) :: :ok | {:error, webhook_error()}

Delivers a signal via webhook.

Parameters

  • signal - The signal to deliver
  • opts - Validated options from validate_opts/1

Returns

  • :ok - Signal was delivered successfully
  • {:error, reason} - Delivery failed with reason

Examples

iex> signal = %Jido.Signal{type: "user:created", data: %{id: 123}}
iex> Webhook.deliver(signal, [url: "https://api.example.com/webhook", secret: "secret"])
:ok

validate_opts(opts)

@spec validate_opts(Keyword.t()) :: {:ok, Keyword.t()} | {:error, term()}

Validates the webhook adapter configuration options.

Parameters

  • opts - Keyword list of options to validate

Options

  • :url - Must be a valid URL string
  • :secret - Must be a string or nil
  • :signature_header - Must be a string
  • :event_type_header - Must be a string
  • :event_type_map - Must be a map of strings to strings

Returns

  • {:ok, validated_opts} - Options are valid
  • {:error, reason} - Options are invalid with reason