Posted on • Originally published atbaldbeardedbuilder.com
Creating Short URLs with Netlify Functions and FaunaDb
Personalized short URLs look so cool. Sure, I could use a service like Bitly. They even provide the ability to use your domain. But I love building things, even when I don't need to. It allows me to explore and learn new things.
I realized I needed a short URL when I started sharing posts from my website, baldbeardedbuilder.com. It's a long one, and that's not considering slugs. So I went on the hunt for something super short and found bbb.dev. It's perfect! I purchased it quickly and got to work.
Storing URLs
First up was keeping up with the short/long URL pairs. I knew I'd be looking for a database, and having usedFauna in the past, I decided it would work well for this application. My site doesn't get a lot of traffic, so I expected their free tier to cover me.
Update: this function has been running for well over a year and I still don't come close to fully utilizing Fauna's free tier.
Data Structure
In my Fauna account, I created a new database namedsmolify
with a collection namedShortyMcShortLink
. Why those names? Because I like to think my dad-joke brain is clever. 😁
Next, I added an initial record. I knew it needed a short code and a full URL, but I also thought it would be cool to track how many visits that short URL had been used. So I added avisits
property to keep track of that. My first short URL would be used for the BBB community code of conduct and looked like the
following:
{"source":"coc","target":"https://baldbeardedbuilder.com/code-of-conduct/","visits":0}
Whenever I need a new short URL, I log into Fauna and create a new document in that format with the correspondingsource
andtarget
.
Retrieving Data
With data in my collection, I needed a way to grab specific records based on thesource
property. To do that, I created an index namedshortyMcShortLinkBySource
. Again, I apologize for my dad-joke-inspired naming conventions. 🙄
That index has one 'term' that it watches; thesource
property.
Creating the Netlify Function
Once the database was ready, I moved to create a serverless function to retrieve and update data. My site is currently hosted onNetlify, so their functions seemed like a great place to start.
I created a new JavaScript file namedsmolify.js
and added my dependencies.
import{Client,query}from'faunadb';require('dotenv').config()exports.handler=async(event)=>{}
Finding the Short Code
First, I needed to find the short code and get the long URL. To do that, I created thegetLongUrl
function. It takes a path (in this case, the short-code) and finds it in the index I previously set up.
ThemapResponse
function performs a little mapping to make it easier to identify theid
assigned by Fauna for later use and then return the record Fauna found. If anything goes wrong it returns undefined.
constgetLongUrl=async(path)=>{try{constresponse=awaitclient.query(query.Map(query.Paginate(query.Match(query.Index("shortyMcShortLinkBySource"),path)),query.Lambda("ShortyMcShortLink",query.Get((query.Var("ShortyMcShortLink"))))))if(response.data&&response.data.length>0){constshortUrl=mapResponse(response.data[0])returnshortUrl}}catch(err){console.log(err)}returnundefined}functionmapResponse(payload){return{...payload.data,_id:payload.ref.value.id}}
Counting Visits
Before I send the result back to the browser, I want to record the visit to Fauna. To do that, I created therecordVisit
function below. It increments the visit count that Fauna provided and then replaces that object based on the Faunaid
that we mapped.
constrecordVisit=async(shortUrl)=>{try{shortUrl.visits++awaitclient.query(query.Replace(query.Ref(query.Collection("ShortyMcShortLink"),shortUrl._id),{data:shortUrl}))}catch(err){console.log(err)}}
Then I updated thegetLongUrl
function to add a call torecordVisit
between mapping and returning it.
constshortUrl=mapResponse(response.data[0])awaitrecordVisit(shortUrl)returnshortUrl
Finishing Our Function
With the JavaScript ready, I added it to the handler function. First, it calls thegetLongUrl
function with theevent.queryStringParameters.path
. I'll cover changing/coc
to/?path=coc
later.
If the function can find a short URL, theredirectUrl
variable is set to itstarget
property. If it returns undefined, the function will redirect the person to the homepage of baldbeardedbuilder.com.
exports.handler=async(event,context)=>{constshortUrl=awaitgetLongUrl(event.queryStringParameters.path)constredirectUrl=shortUrl?shortUrl.target:'https://baldbeardedbuilder.com/'return{statusCode:302,headers:{location:redirectUrl,'Cache-Control':'no-cache',},body:JSON.stringify({}),}}
Configuring Netlify
All that was left was to redirect the traffic using the short URL to the function. Luckily, Netlify makes that a pretty quick process. First, I added the domain to my Netlify application. Once it was set up and sending traffic to the site, I set up the redirect on Netlify.
Redirecting the Short URL
At the root of the site, I added anetlify.toml
file with the following snippet:
[[redirects]]from = "https://bbb.dev/*"to = "/.netlify/functions/smolify?path=:splat"status =301force =true
This takes all traffic tohttps://bbb.dev
and redirects it to thesmolify
function. When redirecting, it adds the splat from thefrom
filter as a querystring parameter namedpath
.
Remember thepath
parameter I was grabbing in the function? This is where it's coming from.
Wrap Up
Then I deployed everything to the site. All traffic to the short URL is redirected to the Netlify function and I can add as many short codes as I need by adding a record to my Fauna database.
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse