Build a link shortener in under 50 lines of code with Cloudflare Workers and KV
I’ve been hearing a lot about Cloudflare lately, a few weeks about I read a post by Troy Hunt where he talks about one of his recent experiences using Cloudflare Workers. Prior to this I had read about doom scrolled past tweets about Workers, but never had a chance to try them out. And again this weekend someone I follow on Twitter posted about Workers again, so I figured it was now time to give them a try.
What are Cloudflare Workers and KV?
If you aren’t familiar with Workers or KV then be sure to take a look at the Cloudflare documentation as it is extensive and very well written.
This is straight from the Cloudflare docs:
Cloudflare Workers provides a serverless execution environment that allows you to create entirely new applications or augment existing ones without configuring or maintaining infrastructure.
And Cloudflare Workers KV again from the docs
Workers KV is a global, low-latency, key-value data store. It supports exceptionally high read volumes with low-latency, making it possible to build highly dynamic APIs and websites which respond as quickly as a cached static file would.
Setting up
With those definitions and background out of the way it’s time to setup the various bits for our link shortener. The first thing you’ll need is a Cloudflare account - which is free - and ideally you will also have a domain name but this isn’t required (although Cloudflare will ask you about this when you signup). I’ve setup my unravelled.dev domain to use Cloudflare DNS which will come in handy at the end of this post, however you can follow these steps with an unverified domain.
Head over to http://www.cloudflare.com to sign up for a free account.
Workers KV
Once you’re signed up the next thing to do is create the Workers KV. To do this browse to the Workers section and click on Manage KV namespaces. This will list all your existing Workers KVs and give you the option to add a new Namespace. I’ve called mine SHORT_LINKS
.
We will come back to the KV at the end of the setup process.
Worker
The next step is to create the Worker. This can be done locally using the wrangler
cli which is provided by Cloudflare, but I found getting going via the in-browser editor a good experience. It also means you don’t have to mess about getting components installed and authenticated.
Browse to the Workers Overview and click on Create a Worker, this will open up the inbrowser editor experience with a sample Worker.
Click Save and Deploy to deploy the sample, we’ll come back in just a minute and modify the implementation. Once it has been deployed you can click the Send button to test it out.
Binding the Worker KV and Worker
The last setup task that needs to be done is binding the Worker KV to the Worker. Click the back button to go to the Worker overview, then Settings and scroll down to KV Namespace Bindings.
Click Add binding and set variable name to SHORT_LINKS
and then select SHORT_LINKS
from the namespaces dropdown.
Show me the code
With the building blocks in place it’s time to start writing some code. The Worker is going to serve two purposes. First, when handling a POST
request, it will take a URL from the request body and return a short link in the response body. Second, when handling a GET
request it will use the path of the URL to look up the associated full URL that’s stored in the SHORT_LINKS KV.
Generating short links
Let’s take a look at the code required to handle POST
requests.
|
|
A worker is made up of two parts, first there is always an event listener which is listening for fetch
events and second an event handler which returns a response. Lines 1-7 show the event listener, which passes through the incoming request to the event handler function handleRequest
.
In the code above you can see in the handleRequest
method the first thing I’m doing is checking request.method === "POST"
and if it does then I’m getting the request body as json (line 19), generating a random hash (line 20) using a method that I found on Stackoverflow.
The interesting part is line 21 where the full url from the request body is stored along with the hash into my SHORT_LINKS
KV, it’s not actually very interesting because it’s just so simple, kudos to Cloudflare 🙌 for making things so easy.
The rest of this block then returns a response containing the short link url to the caller. With the in-browser editor we can take this for a quick spin.
If we browse back to the Workers KV then we can see that the hash and shortlink have been stored successfully.
Retrieving short links
Now that short links can be stored when the Worker receives a POST request, the next step is to handle GET requests and forward the user to the correct location.
|
|
Now when someone browses to our Worker URL this snippet of code will be executed. There isn’t much to this, lines 2-4 get the hash from the request.url
, then on line 5 the hash is used to look up the value from the SHORT_LINKS
KV. If there’s no value then the result is null and the Worker resonds with a 404, if a result is found then a Response.redirect
is returned and the user is redirected.
Putting it all together
Here is the full code of my Worker, it includes an extra bit which returns a 405
if it receives a request that isn’t a GET or POST or request. The other thing to note is that the baseUrl
on line 18 is the URL of the Worker.
|
|
Taking it further
The last thing that can be done to make this a more complete example is to setup a route for the Worker, this means that Cloudflare can be configured with a custom DNS entry for the Worker - so that you can use your own domain. For details checkout the excellent Routes documentation.
Something else you would probably want to do is put authentication in place so you can control who can generate shortlinks. I’ll save that exercise for the reader 🙂 (hint, there are plenty of examples available).
This post can be accessed via https://go.unravelled.dev/kkiyt served up using the above Worker.
🍪 I use Disqus for comments
Because Disqus requires cookies this site doesn't automatically load comments.
I don't mind about cookies - Show me the comments from now on (and set a cookie to remember my preference)