View Source GitHub.Webhook (GitHub REST API Client v0.3.3)
Helpers for validating and handling webhooks dispatched by GitHub
This module is made for Plug / Phoenix applications that wish to accept webhook requests that are sent from the GitHub API. Receiving these requests requires setting up a webhook or GitHub App, which is out of scope for this documentation.
configuration
Configuration
In order to validate that incoming webhooks are, in fact, from GitHub, it is strongly
advised to set a webhook secret. This is a secret value that you generate and supply to GitHub
in the webhook or GitHub App settings. If you are using Phoenix, an easy way to generate this
value is by running mix phx.gen.secret
.
Then, supply this value to the library at runtime using the following configuration:
config :oapi_github,
webhook_secret: "my secret"
It is common to use System.fetch_env!/1
or a similar function to load this type of secret
from environment variables. Alternatively, the webhook secret can be supplied directly to
verify_github_signature/2
at compile time.
usage
Usage
If the optional dependencies Plug
and Plug.Crypto
are installed, this module provides
several helpers to simplify the process of handling webhook requests. A typical webhook
controller might look like this:
defmodule MyAppWeb.GitHubController do
use MyAppWeb, :controller
import GitHub.Webhook
plug :verify_github_event
plug :verify_github_signature
def webhook(conn, params) do
# Handle the webhook...
end
end
In order to perform verification of the signature, it is necessary to store the original request
body in an assign :raw_body
or :body
. This usually requires implementing a custom
Plug.Parser
for webhook requests.
See verify_github_event/2
and verify_github_signature/2
for more information.
Link to this section Summary
Functions
Construct the value of the :body_reader
option for Plug.Parsers
for caching request bodies
Cache request body as :raw_body
assign for chosen connections
Get and store the GitHub webhook event type
Check the validity of a GitHub webhook request
Link to this section Functions
Construct the value of the :body_reader
option for Plug.Parsers
for caching request bodies
This function, called at compile time, creates a valid value for the :body_reader
option in
a call to the Plug.Parsers
plug. Usually called in a Phoenix Endpoint, the code looks like:
plug Plug.Parsers,
parsers: [:json, ...],
json_decoder: Jason,
# ...
body_reader: GitHub.Webhook.body_reader()
It sets up cache_request_body/2
as the body reader, which will in turn cache the raw request
body as an assign :raw_body
for use during signature verification.
options
Options
:fallback
: If using the:routes
option below, which body reader function to call for requests that do not match one of the specified routes. Defaults to{Plug.Conn, :read_body, []}
.:routes
: Optionally restrict the caching of request bodies to specific routes, given as a list of strings (ex.["/hook/github"]
). Defaults to caching request bodies for all requests, which can cause a significant performance impact.
@spec cache_request_body(Plug.Conn.t(), keyword(), keyword()) :: {:ok, binary(), Plug.Conn.t()} | {:error, term()}
Cache request body as :raw_body
assign for chosen connections
This function adheres to the needs of the :body_reader
option for the Plug.Parsers
plug. It
saves the raw request body as a binary to the :raw_body
assign on the Plug.Conn
, so that it
can be used for signature verification later.
This function is not usually called directly. Instead, use body_reader/1
.
@spec verify_github_event( Plug.Conn.t(), keyword() ) :: Plug.Conn.t()
Get and store the GitHub webhook event type
This function looks at the X-GitHub-Event
header to ensure the incoming request is a webhook
event and stores the event as a :github_event
assign on the connection. If the header is
missing, the connection is immediately halted with a simple error message that will appear in
GitHub's UI.
@spec verify_github_signature( Plug.Conn.t(), keyword() ) :: Plug.Conn.t()
Check the validity of a GitHub webhook request
This function uses the configured :webhook_secret
or an option :secret
to verify the
signature of an incoming GitHub webhook. If the signature is missing or invalid, the connection
is immediately halted with a simple error message that will appear in GitHub's UI.
configuration
Configuration
:webhook_secret
: Secret given to GitHub to use when signing webhook requests. If not supplied via configuration nor the:secret
option, an error is raised.
options
Options
:secret
: Compile-time secret to use as the webhook secret. If not supplied at compile time nor via the:webhook_secret
configuration, an error is raised.