Exposing Callback and Webhook URLs on Localhost

by Matt Robison

There are many services out there that want to talk to your application. An event happens, such as a new subscriber, and the service wants to tell you about it. Often, this functionality is implemented via a webhook pattern, where your application exposes a public url for the express purpose of receiving such communication.

Let me offer an example. I recently needed Mailchimp to send me a notification whenever a campaign was sent to one of our mailing lists. But how to test this? Mailchimp needed a URL it could access publicly, but I didn’t want to test anything on a live, public server. That would be time consuming, and probably a little dangerous. I needed to expose a public URL from my local machine.

There are a few tools that offer this functionality, but the best was ngrok. After downloading the tool, you can run it via the command line. The following commands assume a linux/Mac computer. If you are on Windows, just ignore the “./” in front of the command.

./ngrok http 80

This brings up a UI with some information.

ngrok command line ui

You get a temporary hash subdomain (03fcdb2a) that is now forwarded to your localhost. And you can see connections as they happen. Pretty cool. This is the domain I needed to put into the Mailchimp settings, so it knows where to send updates.

If your app is actually running at localhost on port 80, this is all you need to do. Chances are, however, that you have more than one development environment. How do you point to the right one?

Virtual Hosts and Virtual Machines

If you are running Apache locally as your webserver, you might have several virtual hosts set up to respond either to different port numbers or different host headers. If you have distinguished them with ports, just put a different port number in the command.

./ngrok http 5000

If your virtual hosts will only respond to a certain host header, there’s an option for that:

./ngrok http -host-header=example.local 80

If you use vagrant and virtual machines, ngrok can work for you too. Just ensure that traffic is forwarded to the local hostname of your vagrant instance:

./ngrok http -host-header=example.local example.local:80

Now we have a public URL that is forwarded to a place on our local machine. An outside service can send us data. But now we need to test how everything is working together, and ngrok provides some tools that make this easier.

Faster Development with Replay

One of the most useful features of ngrok is the web interface. It provides local access to one for each connection you forward.

ngrok web dashboard

Here you can view both the request you receive and the response you send. The default is an easy summary of the post data, but you can view it raw, or even in binary if you want. If you’re having issues, this dashboard is one of the first places you should look, since it can even help you pinpoint problems coming from the source service.

The most useful feature of this dashboard is the replay functionality. It’d be tedious to send a test campaign every time I wanted to test the webhook from Mailchimp. Instead, I click the replay button, and ngrok will resend the same request.

Similar Tools

There are other tools, like Ultrahook and localtunnel, that offer similar functionality, but I found ngrok the best to work with for a few reasons:

It has no dependencies. No need to mess with Ruby gems or npm.

Lots of flexibility that is well documented. Add your own subdomain or custom domain, HTTP authentication, and more. Modifying the host header, as I did above, wasn’t possible with some of the other tools.

The user-friendly dashboard with replay functionality is specifically made for developing for things like webhooks.

Bonus: Responsive Design Testing and Other Collaboration

Developing responsive websites becomes a little easier with the help of ngrok. Do you have several devices you want to test your web application on, but don’t want to push anything up to a publicly accessible server? Serve it from your local machine.

If Mailchimp and other services can reach your localhost, so can your own collection of various-sized devices. And so can your co-workers, no matter where they are located.