Fivetrex.WebhookPlug (Fivetrex v0.2.1)
View SourceA Plug for handling incoming Fivetran webhooks in Phoenix/Bandit applications.
This plug verifies webhook signatures and parses the payload into a
Fivetrex.Models.WebhookEvent struct, making it easy to integrate Fivetran
webhooks into your Phoenix application.
Features
- Verifies HMAC-SHA256 signatures to ensure requests are from Fivetran
- Parses webhook payloads into typed structs
- Returns appropriate HTTP error responses for invalid requests
- Assigns the parsed event to the connection for downstream handlers
Installation
Step 1: Capture Raw Body
This plug requires access to the raw request body for signature verification. Add a body reader to your endpoint:
# In lib/my_app_web/endpoint.ex
plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
body_reader: {Fivetrex.WebhookPlug, :cache_raw_body, []}, # Add this
json_decoder: Phoenix.json_library()Step 2: Add Route
Add a route for the webhook endpoint:
# In lib/my_app_web/router.ex
scope "/webhooks", MyAppWeb do
pipe_through :api
post "/fivetran", FivetranWebhookController, :receive
endStep 3: Use the Plug
Add the plug to your controller:
defmodule MyAppWeb.FivetranWebhookController do
use MyAppWeb, :controller
plug Fivetrex.WebhookPlug,
secret: {MyApp.Config, :fivetran_webhook_secret, []}
# Or: secret: "my_static_secret"
# Or: secret: {:system, "FIVETRAN_WEBHOOK_SECRET"}
def receive(conn, _params) do
event = conn.assigns.fivetran_event
case event.event do
"sync_end" ->
# Handle sync completion
handle_sync_end(event)
"sync_start" ->
# Handle sync start
handle_sync_start(event)
end
json(conn, %{status: "ok"})
end
endConfiguration Options
:secret- Required. The webhook secret for signature verification. Can be provided as:- A string:
secret: "my_secret" - A tuple for runtime fetching:
secret: {Module, :function, args} - A system env tuple:
secret: {:system, "ENV_VAR_NAME"}
- A string:
:event_key- Optional. The key to use inconn.assignsfor the parsed event. Defaults to:fivetran_event.:on_error- Optional. A function to customize error responses. Signature:fn conn, error_type -> conn. Defaults to sending JSON errors.
Assigns
On successful verification, this plug adds:
conn.assigns.fivetran_event- The%Fivetrex.Models.WebhookEvent{}structconn.assigns.raw_body- The raw request body (for debugging)
Error Handling
Invalid requests receive appropriate HTTP responses:
400 Bad Request- Missing signature header401 Unauthorized- Invalid signature422 Unprocessable Entity- Invalid JSON payload
See Also
Fivetrex.WebhookSignature- Low-level signature verificationFivetrex.Models.WebhookEvent- The event structFivetrex.Webhooks- API for managing webhooks
Summary
Functions
Custom body reader that caches the raw body for signature verification.
Functions
@spec cache_raw_body( Plug.Conn.t(), keyword() ) :: {:ok, binary(), Plug.Conn.t()} | {:more, binary(), Plug.Conn.t()}
Custom body reader that caches the raw body for signature verification.
Use this as the :body_reader option in Plug.Parsers:
plug Plug.Parsers,
parsers: [:json],
body_reader: {Fivetrex.WebhookPlug, :cache_raw_body, []},
json_decoder: Jason