Webhooks behind the firewall with Reverse HTTP

By: on July 21, 2009

With the growing popularity of building webhooks to link applications together, and the stunning ease of building web applications with lightweight web frameworks in various languages (such as Sinatra in Ruby), the thorny issue of NAT-firewalls remains a substantial dampener on development ease. Enter another use for Reverse HTTP. With Reverse HTTP, applications running behind a firewall can be attached to a public server without any firewall changes, and accessed as if they belonged to the public server.

Brought to you through the magic of the Ruby Rack interface, I’d like to announce Hookout. Hookout provides an adapter for Rack-based ruby applications to make the application directly available to the outside world via a Reverse HTTP server.

As an example, take the GitHub post-receive hook sample detailed in their documentation at http://github.com/guides/post-receive-hooks. It consists of a ruby app (for this example, call it github-hook.rb):

require 'rubygems'
require 'sinatra'
require 'json'

post '/github' do
  push = JSON.parse(params[:payload])
  puts "I got some JSON: #{push.inspect}"

And you’ll also want a rackup configuration file (call it config.ru):

require 'github-hook'
set :run, false
run Sinatra::Application

Before you can run this with Reverse HTTP, you’ll need to install the hookout gem. Assuming that you have a working Ruby environment, install the dependencies then Hookout itself. (Note that the gem sources line is only required if you’ve never installed gems from github before):

sudo gem install sinatra thin
sudo gem sources -a http://gems.github.com
sudo gem install paulj-hookout

To run this, come up with a novel name (eg, mygithub-hook), and execute:

hookout -a http://www.reversehttp.net/reversehttp -n mygithub-hook -R config.ru start

(Note, if you don’t pick a novel name and change the -n statement, then it is possible you might clash with someone else on the server. If things don’t work as expected, pick a new name and try again…)

Once the app starts, you should see a line reading:

Bound to location http://mygithub-hook.www.reversehttp.net/

Go to a Github project you have control over, enter the Admin section, then the Service Hooks subsection. From here, you can add a reference to your hook. Hit Update Settings, then click “Test Hook”. After a few seconds, you should see the details of the GitHub test appear in your console. Your webhook has just worked from behind a firewall!

Hookout is available on GitHub at http://github.com/paulj/hookout/tree/master.



  1. roger says:

    looks great! but can’t get it to work with jruby though. do you have any suggestions ?

  2. paulj says:

    The actual code itself is relatively simple – I’d suspect that the problem is with Thin not being available on JRuby (https://thin.lighthouseapp.com/projects/7212/tickets/13-get-working-on-jruby). The Hookout code currently uses Thin for two things – the HTTP parser component and as management for daemonization when run with the command line. The actual Reverse HTTP connector is free of these dependencies however, so it would be entirely possible to use a more JRuby dependency for the other parts.

  3. Tony Garnock-Jones says:

    One possibility for JRuby might be to use reversehttp’s java classes: http://github.com/tonyg/reversehttp/tree/master/priv/java/src/main/java/net/reversehttp

  4. selem says:

    have you tried tihs with file uploads? small files are ok, but anything larger than 500k gives an error.

  5. Thanks for this! This is genius. I’ve been playing with this Ruby/Hookout/Sinatra example and my mind is blown away by the possibilities it opens up. As an example: mobile data synchronization to an application behind a firewall. You establish a unique reversehttp listener from the application behind the firewall. From the mobile device you push data to a cloud database, then subsequently fire a request to the public reversehttp address. This is caught behind the firewall and the application wakes up and gets the data from the cloud. No polling!

    Of course, I could also get rid of the cloud database entirely by enhancing the interface of the ruby app.

  6. paulj says:

    Great to hear that you’re getting some use out of it!

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>