Back to blog
LOCAL DEVELOPMENT, API DEVELOPMENT

Efficient Webhook Testing with Blackbird: Easy API Integration & Debugging

Matt Voget
September 23, 2024 | 5 min read
Efficient Webhook Testing

When building integrations with 3rd party applications such as Stripe, PayPal, or GitHub managing webhook handling can be tricky. Webhook testing becomes challenging because it relies on the third-party app to send a request to your API, - and in development your server is usually running at localhost.

In this guide, I’ll show you how to use Blackbird API development tool to simplify webhook testing by generating a public URL for development and debugging webhook requests.

Example: GitHub Commit Tracker

Let’s set up a server that handles webhook requests from GitHub. Suppose we’re building an app that tracks commits to a GitHub repository. To follow along, clone the Commit Tracker App (written in Go).

git clone https://github.com/matty-v/commit-tracker
cd commit-tracker
go run cmd/commit-tracker/main.go

You can test the webhook endpoint locally with a POST request:

curl --request POST -d '{
"ref":"refs/heads/main",
"commits":
[
{
"id":"abc123",
"message":"Updated a file",
"timestamp":"2024-09-18T00:00:00-06:00",
"author":
{
"email":"test@example.com",
"name":"Some Committer"
}
}
]
}' localhost/v1/webhook

The test works locally, but to handle real webhook testing, we need a public URL—this is where Blackbird API development tool comes in.

Setting Up Blackbird for Webhook Testing

  • Install the Blackbird CLI on your laptop.
  • Log in with blackbird login to provision a personal remote environment for testing.

Run Webhook Testing with Blackbird

Instead of using

go run
I'll issue the following Blackbird command:

blackbird code run commit-tracker -d Dockerfile -c . -l 80
✔ image successfully built
✔ connected to Matt's organization blackbird environment 0
✔ temporary instance created
+----------------+------+--------+----------------+---------------------------------------------------------------------------------------------+------------+
| NAME | TYPE | STATUS | APIKEY HEADERS | URL | CREATED BY |
+----------------+------+--------+----------------+---------------------------------------------------------------------------------------------+------------+
| commit-tracker | Code | Ready | | https://default-blackbird-matts-organization-5b603-0.blackbird-relay.a8r.io/commit-tracker/ | Matt Voget |
+----------------+------+--------+----------------+---------------------------------------------------------------------------------------------+------------+
✔ type <ctrl>-C to end...

Here is what Blackbird did behind the scenes:

  • Containerized my app and is running it in Docker on my local machine, exposing port 80
  • Generated a public URL in my personal remote environment
  • Actively routing traffic from the public URL directly to the local container

Now if I send that same curl command to test the webhook using the Blackbird provided URL I can see that my local server is responding the same way!

curl --request POST -d '{
"ref":"refs/heads/main",
"commits":
[
{
"id":"abc123",
"message":"Updated a file",
"timestamp":"2024-09-18T00:00:00-06:00",
"author":
{
"email":"test@example.com",
"name":"Some Committer"
}
}
]
}' https://<my-env>.blackbird-relay.a8r.io/commit-tracker/v1/webhook

Be sure to replace

<my-env>
with the specific name of your environment as provided by Blackbird.

Let's go over to GitHub now to setup and test the webhook from the repo whose commits I wish to track. I can do this by navigating to Settings > Webhooks > add webhook

The Payload URL is the endpoint where GitHub will deliver the webhook request. Use the URL provided by Blackbird (e.g.

https://<my-env>.blackbird-relay.a8r.io/commit-tracker/v1/webhook
). Also be sure to check the "send me everything" option to get commit data.

With the webhook created, you can now test it out by making commits on the repo and see that your locally running code is handling it!

2024-09-18T21:02:30Z INF commit-tracker server is starting up
2024-09-18T21:02:30Z INF starting commit-tracker server, address: :80
2024-09-18T21:03:06Z INF POST /v1/webhook 200 729.608µs
[{{matt.voget@gmail.com Matt Voget} eec15... Update README.md 2024-09-18T12:05:32-06:00}]

When I'm done testing, I can ctrl-c on the command line to end the Blackbird code run session and kill the public URL.

Debugging webhooks with Blackbird

Let's pretend that I wasn't perfect and accidentally introduced a bug in my webhook handler code. I can use Blackbird to attach a debugger to my code to step through breakpoints as the webhook is being received.

To follow along, you can uncomment the

//decoder.DisallowUnknownFields()
line in
handlers.go
in the commit tracker code:

// HandleHandleWebhook handles parsing input to pass to the HandleWebhook operation and sends responses back to the client
func (h *APIHandler) HandleHandleWebhook(w http.ResponseWriter, r *http.Request) {
var err error
reqBody := GitHubWebhook{}
decoder := json.NewDecoder(r.Body)
decoder.DisallowUnknownFields()

This will make the handler reject webhook requests where the payload does not match the

GitHubWebhook
schema in the commit-tracker code. Perhaps you develop and test against a mocked GitHub client sending webhooks without all the payload fields. You may find your code working in dev and test, but failing when it hits production!

Here's how to use Blackbird to debug this problem

blackbird code debug commit-tracker -d Dockerfile -c . -l 80

Once more, Blackbird containerized my code, but this time it followed instructions in the Dockerfile to build the image with debug symbols and expose port

2345
for a debugger to attach to.

In VSCode, I defined a

launch.json
debugger config with instructions to attach at that port:

{
"version": "0.2.0",
"configurations": [
{
"name": "Connect to server",
"type": "go",
"request": "attach",
"mode": "remote",
"port": 2345,
"host": "127.0.0.1"
}
]
}

Now that I have attached the debugger, I can once more deliver a webhook from GitHub to the same public URL:

https://<my-env>.blackbird-relay.a8r.io/commit-tracker/v1/webhook

This time, I can hit breakpoints and step through my code to see what's happening

debugging with Blackbird

Enhanced Security: No Tunneling, Secure Connections, and API Key Protection

Unlike other tools out there, Blackbird does not use tunneling to open traffic from the public URL to your localhost, nor will it modify your local machine's host network or DNS. It instead will leverage Docker's local container networking to establish a secure connection to the remote host - think of it like a mini-VPN. Out of the box, this significantly decreases the attack surface area for malicious actors who get access to the public URL.

Also, Blackbird has an ability to pass a custom-defined API key to

blackbird code run
and
blackbird code debug
commands. This will protect your public URL from being used by anyone who does not pass that key as a header in a request. To find out more, read the docs around securing Blackbird instances.

Wrapping Up

In this guide I showed how you can use the Blackbird CLI to test webhooks by using the

blackbird code run
and
blackbird code debug
commands.

Blackbird API Development Tool

Secure and Seamless Webhook Testing with, Try it now