When an event happens, we make an HTTP POST request to our client’s URL
Boom, Webhooks!
The Benefits
#1
We write the code
#2
Fewer resources required
#3
We send the data just as it changes
This is Real-Time™
Exciting for integration!
It’s like Push Notifications for the web
We’ve got our background!
How about implementing it?
Let’s see a small example
Show us making a single request
Start small & build momentum
Random Number Generator
require_relative '../lib/webhooks'
class RandomNumberGenerator
include Webhooks
def initialize
self.webhooks = %w{http://localhost:9000}
end
def generate
random_number = SecureRandom.random_number(1000)
send_webhooks(:random_number, :generate, random_number)
return random_number
end
end
require 'net/http'
require 'securerandom'
require 'json'
module Webhooks
attr_accessor :webhooks
def send_webhooks(resource, action, data)
event_type = "#{resource}:#{action}"
payload = JSON.generate({
event: event_type,
data: data })
webhooks.each do |webhook|
url = URI.parse(webhook)
Net::HTTP.start(url.host, url.port) do |http|
headers = { 'Content-Type' => 'application/json' }
response = http.post('/', payload, headers)
end
end
end
end
Client code
...
class Polis < Sinatra::Base
...
post '/' do
# Note: Thanks to this SO page: http://stackoverflow.com/a/6318491/249218
http_headers = env.select{|h| h =~ /HTTP_/}
body_string = request.body.read
...
logger.info <<-LOG
Logging POST request:
Headers:
#{http_headers}
Body:
#{body_string}
LOG
status 200
return body_string
end
...
end
We sent our first webhook!
There’s no official spec
It’s a general practice to
Send data to a URL
when something happens
How about another demo?
push a button on a site
generate a random number
send a text message
Random Number Button
Before we push the button
After we push the button
And the text sent
Client code
...
class RandomNumberTexter < Sinatra::Base
...
post '/' do
request.body.rewind
post_body = request.body.read
if request.content_type == 'application/json'
payload = JSON.parse post_body
is_random_number_generate = payload['event'] == 'random_number:generate'
return unless is_random_number_generate
has_payload_data = payload['data']
return unless has_payload_data
random_number = payload['data']
send_text(random_number)
status 201
else
status 202
end
post_body
end
...
end
It still feels like magic
What Can I Do With Them?
Workflows are suddenly much easier
Post support emails, chat requests, and help forum posts in support
chatroom
Kick off continuous integration build after pushing commits to GitHub
Post to engineering chatroom when CI build/tests fails
Text employee when they’ve been assigned work
Reorder products, when inventory drops below threshold