Webhook Forwarding

Webhook Relay provides public endpoints which can accept webhooks and then, based on user defined rules, forward them to either public or internal destinations.

Our service has a concept of bucket which is basically a grouping mechanism that enables you to accept webhooks on multiple endpoints and forward them to one or more destinations. Bucket inputs are configurable and can return custom responses, while outputs can have filtering rules and forward webhooks to both internal or public destinations:

Bucket design

A newly created bucket will have a default input and will request you to create an output destination:

New Bucket

If it’s a public destination, add the name, HTTP URL and click ‘create output’. All received webhooks will be forwarded to that destination.

If it’s an internal destination, check ‘internal network’ and start a relay agent:

$ relay forward --bucket new http://localhost:8080
Forwarding:
https://my.webhookrelay.com/v1/webhooks/2e50b993-ac45-48f7-b840-eb054b19e630 -> http://localhost:8080

What can be forwarded?

Currently Webhook Relay forwards:

Ephemeral webhooks (no logs)

Buckets can be configure to be ephemeral so that request method, headers, query and body will not be saved to the database. To do this, go to bucket details page, click on Configure button and tick Ephemeral webhooks box. All new webhooks will not have their details saved. When ephemeral mode is on, you will not be able to:

New webhook logs will appear like this:

Ephemeral logs

Response body settings

Sometimes applications that send webhooks accept certain headers, status code or body. To configure these settings, go to your bucket details and click on a settings icon near the input URL that you want to configure:

Input URL response settings

Configuration looks like:

Input URL response configuration

If you need more specific or dynamic configuration, consider using bidirectional tunnels with your own server on the backend.

Overriding webhook headers

Output configuration allows overriding request headers so users can add any headers on top:

Configure output

You can also update output destination and headers through CLI:

relay output update OutputName --bucket Test --header secret-token=123456 --destination https://127.0.0.1:1880

Enabling/disabling TLS verification

You can control TLS verification for each output individually. To enable or disable TLS verification, go to your output settings:

Configure output TLS verification

Request matching rules

Rules can be applied on each output to filter incoming requests. There are a number of different configurations that allow:

Below, there are several examples to do matching based on URL queries and request bodies.

Matching based on URL query

Value match

Let’s create a rule that checks whether URL query has a specific parameter that matches our given value:

Configure URL match based on value

With this configuration, if we send a webhook to https://my.webhookrelay.com/v1/webhooks/aa4d6bb5-87b6-4041-b5f4-a768338425c6?name=john, rule will extract and match parameters name=john.
While https://my.webhookrelay.com/v1/webhooks/...?name=john will be matching the rule, a webhook to https://my.webhookrelay.com/v1/webhooks/...?name=tom will not be relayed.

Regular expressions

To match based on regular expressions, select regex rule type:

Configure URL match based on regular expression

With this configuration, a webhook request query will have to have a location parameter with value either london or paris: https://my.webhookrelay.com/v1/webhooks/...location=paris

You can view regex examples here: https://golang.org/pkg/regexp/syntax/

Contains or Does Not Contain

There are additional matching types such as contains and does not contain. These are general purpose, easy to use matchers.

Matching based on request body

Body matching can be achieved by:

value

Value type rule can match a parsed payload of a JSON webhook and check whether a specified parameter matches the rule value:

Configure body match based on value

Only webhooks that have id = foo inside the nested ‘data’ key will be passed:

{
"status": "xx",
"data": {
"id": "foo"
}
}

does not contain

Regex rules can match based on specified parameters when JSON body is parsed:

Does not contain for request body

With this configuration, a request with payload:

{
"status": "xx",
"data": {
"id": "xxx"
}
}

will be matched by a rule and passed through, while this one:

{
"status": "ff",
"data": {
"id": "foo"
}
}

will be rejected as it contains our unwanted value.

contains

Contains matching is one of the simplest examples:

Configure body match based on phrase

Select a contains rule type and type a string that should be in the request body:

{
"status": "ff",
"data": {
"id": "london"
}
}

This payload will be relayed.

If body is not JSON, ‘contains’, ‘regex’ or ‘does not contain’ will be matching against plain text body.

Matching based on request headers

Similarly to URL query and request body matching, header rules can extract and compare values from headers:

Header rules

Validating webhook SHA1 and SHA256

Rules can perform both SHA1 and SHA256 webhook payload signature validation. For that, you need to choose header as the source, set parameter to the name of the header that will have the hash, select either ‘payload SHA1’ or ‘payload SHA256’ from the menu and set your secret in the value field:

SHA1 validation

Grouping

Rules can be grouped using logical operators all and any which are equivalent to and and or if you are familiar with programming principles. You can have multiple levels of rules interacting with each other.