Develop webhooks locally using Tailscale Funnel
Time to read: 5 minutes
Webhooks are a way to be notified by an external service when an event has occurred. Instead of you sending an HTTP request to that service, the service sends an HTTP request to your public web service. This way, you can respond to the event in real-time. Webhooks are also a common way to integrate with Twilio's products. For example, when your Twilio phone number receives a text message or phone call, Twilio sends an HTTP request (the webhook) to your service with the details. Your service then responds with instructions that indicate how Twilio should respond to the event. Here's a diagram of what this exchange looks like:
One common challenge with webhooks is that they can only call web services that are publicly available on the internet, but when you are initially developing software, you are typically doing so on your local machine, which by default is not reachable via the internet. So how do you develop and test webhooks on your local machine? The answer: tunnels. In this post, you'll learn how to use Tailscale Funnel, a tunnel service by Tailscale in beta, to make your local web server publicly accessible on the internet. Then you'll learn how to use Funnel to respond to a Twilio webhook to respond to a phone call.
Local tunnels
You can create a tunnel between your local machine and a tunnel service to expose local ports to the public internet. There are many tools that can help you do this, and today you're going to learn about Tailscale Funnel.
Prerequisites
You will need the following things to follow along:
- A Linux, macOS, or Windows machine
- Your development stack of choice (Node.js, PHP, .NET, Java, Python, etc.)
- A Tailscale network also known as a tailnet with your development machine joined to the network. Follow this Tailscale quickstart to do so.
- Optional: A Twilio account (Try Twilio for free)
Set up a local web server
You can tunnel a local port at any time, but you won't see any results if nothing is listening to that port on your machine. In this section, you'll set up a local web server for serving static files.
Open your preferred shell, create a folder, and navigate to it:
Create a new file index.html in the MyStaticSite folder with the following content:
You'll need to run a static web server to serve this HTML file. There are many static servers for every development stack out there. Pick your preferred stack below and follow the instructions to serve the current folder at http://localhost:8080/.
Node.js: Run the following command to execute the http-server NPM package and run it:
PHP: You can use the built-in PHP web server by running the following command:
.NET: You can use the dotnet-serve tool to run a static web server. Install the tool as a global .NET tool:
Run the tool to serve the current directory:
Python 3:
Check out this list of static web server commands if your preferred programming language is not listed above.
Tunnel your local web server using Tailscale Funnel
You can use the Tailscale Funnel to tunnel your local ports to the public internet.
Before you can use Tailscale Funnel, you'll need to:
- Give access to yourself or whoever needs access to this feature
- Enable HTTPS
First, go to the Access Controls in your Tailscale admin page, and add the highlighted JSON (line 29 - 34) to the file and hit Save.
This will give access to Funnel to the autogroup:members group, which are the direct members of your tailnet.
Next, click on the DNS tab and click the Enable HTTPS… button.
Now you should be able to start using Funnel.
Open your preferred shell and run the following commands:
The tailscale serve
command serves your web server running on http://localhost:8080 over HTTPS (port 443) on the current node (your machine) of your tailnet. At this point, your web server is accessible to others on your telnet, but not to the internet.
The tailscale funnel
command creates the tunnel between your locally running server, being served on your tailnet, to the internet over port 443.
Run the following command to see the Funnel status:
The output should look something like:
Copy the URL next to "Funnel on" which is the public URL where you can reach your web server.
Go to the URL using a web browser. You'll see the HTML file that is served from your local web server is now publicly served at the address Tailscale gave you.
You can use this public address and configure it as your webhook address with the external services you want to integrate with.
Use Tailscale Funnel with Twilio webhooks
You can also use these tunnels to respond to Twilio webhooks. In this section, you'll learn how to respond to a phone call using a static XML file.
Create a new file call.xml in the MyStaticSite folder:
This XML file uses TwiML, also known as the Twilio Markup Language. Using TwiML, you can provide instructions on how Twilio should respond to an incoming call or SMS. The TwiML above uses two TwiML Voice verbs: Say
and Pause
. Say
converts text to speech, and the voice
attribute specifies which voice to use. Pause
will wait the specified amount of time, which is one second in this case, and then move on to the next verb.
Make sure your static web server is still running, and browse to the XML file using the publicly tunneled URL: [funnel-url]/call.xml
The XML should be returned to your browser. Take note of this URL.
If you don't already have a Twilio account, you can get a free Twilio account here.
Next, you'll need a Twilio phone number. Go and buy a new phone number from Twilio. The cost of the phone number will be applied to your free promotional credit if you're using a trial account.
Use the left side navigation to navigate to Phone Numbers > Manage > Active numbers. Click on your Twilio phone number to navigate to its settings.
Find the A CALL COMES IN fields under the Voice & Fax section. Change the text field to your public tunnel URL with the /call.xml path, and change the HTTP verb to HTTP GET.
Click Save to submit the form.
To verify the call is working as expected, call your Twilio phone number using your personal phone. You should hear "Twilio received these instructions from your local machine via Tailscale Funnel. Great job!".
Using a static file is sufficient to demonstrate local tunneling, but you can also use the same techniques in combination with any web server technology to process and respond to the HTTP request.
Developing webhooks locally with Tailscale Funnel
Webhooks are a great way to be notified by an external service when an event has occurred. The external service makes an HTTP request to your public web service and provides the details of the event in the body of the request. You can use local tunneling to make your local port accessible on the internet using a tunnel service like Tailscale Funnel. Using Tailscale Funnel, you can tunnel your local port to the public URL provided by Tailscale. Check out the Tailscale Funnel docs to learn more about its capabilities and limitations.
Many Twilio products have webhook capabilities. Learn how you can infuse communication technology into your application in the Twilio Docs, and learn how to get started quickly with Twilio's SDKs.
Niels Swimberghe is a Belgian American software engineer and technical content creator at Twilio, and a Microsoft MVP in Developer Technologies. Get in touch with Niels on Twitter @RealSwimburger and follow Niels’ personal blog on .NET, Azure, and web development at swimburger.net.
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.