Webhooks is merged to master. Please don’t hesitate to leave comments on webhooks feedback.
Webhook is a way to notify external services about changes on the internet. It’s easier to setup, manage and develop than a Discourse plugin. Though, it does require you to program a little bit or understand its technical details.
In this #howto, I’ll set up webhook to power a Github bot for referencing pull request brought in a forum. We’ll want to see a new comment on Github pull request when a new post has a link to it.
It’s a very simple process:
- Publish a new post.
- A webhook event happens, the payload about the new post is sent to the bot on Heroku.
- The bot on heroku parses the payload and check Github for existing comments. Then it creates comment when it feels appropriate.
Setting up the webhook
Firstly, we need a webhook to feed our Github bot. Go to
Webhooks panel and create a new webhook.
A webhook will simply
POST the payload to the given url.
https is strongly recommended. A webhook event may contain sensitive information, for example a reply to message. It may reveal information only available to staff since the payload is generated by
system user. You must fully trust this URL. Here we take a heroku app as an example. (No dash allowed in the url, will fix soon.)
There are two content types available,
application/x-www-form-urlencoded. We prefer json encoding.
The secret is an optional secret key for generate a signature for given webhook event. It’s shared among you and URL you’ve set. Once added, there will be a
X-Discourse-Event-Signature in the HTTP header. It’s computed by sha256. It’s strongly recommended to set up one and verify as the instruction (see below).
For this example, we only make use of post event. You can definitely choose event type you need. Check
Send me everything to receive every event, even the event type we will add in the future.
Triggered categories/groups are advanced features which allows you to filter some event. For example, if only you cares about Staff category, you can add Staff category so that topic event will happen accordingly.
Then, we checked TLS certificate so that we can avoid some network attacks and keep your information secure.
At last, checked active and click create!
Monitor how is the webhook
Go to events or click status information on the left side of webhook list.
Go to list and
Edit webhook allows you to jump around.
Ping is a special button to send a empty event (with no actual payload). It can help you to test your configuration. You should check out your service’s log to see if you receive a Ping event.
You can also read every event to see how it works. We shows the response status code, event id, event happened time and completion time of each event. If you want, the request/response headers and body are available. If you are debugging webhook or your service,
Redeliver button can help you to send the exact request again.
Setting up a Github bot
We want to have a service to notify every mentions to the pull request. We’ll achieve that by hosting a bot on Heroku. It receives webhook event from a Discourse instance and process accordingly.
The code is available here. Simply publish this to a Heroku dyno. Then you’ll need to set up some config envs in the setting page. Check out readme of that repo.
Try it by a reply!
We’ll just need an url to the pull request.
Verify and parse webhook event
Let’s dive in how it works so you can build yourself one. The flow is simple.
- Check out
X-Discourse-Event-Typeto see whether you are interested.
X-Discourse-Eventalso shows the internal event hook.
- Get payload by reading
- Compute sha256 HMAC of raw payload.
To be noted,
X-Discourse-Event-Signature consists of
sha256= and hmac of raw payload.
Webhook event type explanation
The event type is a big category of several
DiscourseEvent under the hood.
Can be restricted by categories.
As you can see, webhook is simply a standard and configured way to notify external services. If you are looking for some kinds of extensions to Discourse based on changes (events) on the forum, consider webhooks. It will be sure to help you with a loosely coupled system. And it shall be much more stable to maintain.