In this blog post, I will guide you through building a serverless URL shortener service built on Upstash Redis, AWS Lambda (Python), and AWS API Gateway. The main purpose of this blog post is to demonstrate the process of creating a Python Lambda function, connecting it to Redis, and consuming it via an API.
You may reach an implementation of the project via: URL Shortener
NOTE: The output URLs are for demonstration purposes; an active URL shortener would have a shorter and simpler domain address, so our focus here is on the functionality.
Project Description
The project consists of one database on Upstash Redis, two Python Lambda functions, and an API Gateway on AWS. Users may use either the web interface or the API to consume the shortener service.
The shortener
Lambda function creates a shortened URL key from a long URL provided in an HTTP request query. It then stores the short URL key and its corresponding long URL value in Upstash Redis, before returning the short URL to the user.
The redirector
Lambda function redirects users from a short URL to its corresponding long URL. It retrieves the long URL from Redis using the short URL key and sends an HTTP 302 redirection response to the user’s browser. This function helps users access the desired content without the need to recall or manually enter the long URL.
Finally, we'll create an API Gateway to consume the Lambda functions. This API will be connected to our basic URL shortener frontend.
Setting up the Upstash Redis
We can create our Redis Database on Upstash Console. After logging in, click the Create Database button. It'll take a few seconds, and you are all set up. Then, copy and paste the UPSTASH_REDIS_REST_HOST
, UPSTASH_REDIS_REST_PORT
and UPSTASH_REDIS_REST_PASSWORD
variables from Details section to a file. We are going to use these keys in the AWS environment variables.
Creating the Serverless Functions on AWS Lambda
Next up, we will create our serverless Python functions. After logging in to AWS, direct to AWS Lambda. From the Dashboard, create the lambda function.
Lambda Function for URL Shortening
The first thing to do is add the environment variables. From the shortener
function overview, go to Configuration > Environment variables > Edit > Add environment variable. Then, type in the UPSTASH_REDIS_REST_HOST
, UPSTASH_REDIS_REST_PORT
and UPSTASH_REDIS_REST_PASSWORD
as the keys, and their corresponding values from Upstash Console.
Now we can start coding. Return back to the Code section of shortener
function, and paste the code below. This will provide us the connection to Upstash Redis Database.
Then we will implement our main shortener algorithm. What the code snippet below does is:
- getting the query parameter
long_url
from the API Request URL, - generating a random 7 character key for the shortened URL,
- setting the value of this key on Upstash Redis to the long URL,
- returning an HTTP 200 Response with our full short URL in the body of the response.
Just below the Redis client creation, add the generate_short_url
and lambda_handler
functions.
Then click Deploy. Even though the codes are ready; if you test the lambda now, you will get the response below from Lambda
Unable to import module 'lambda_function': No module named 'redis'
That is because, in order to use the external Python libraries, we need to create our own libraries as a custom package and then find a way to attach the package to Lambda. There are several ways to resolve this, but my go-to solution would be using Lambda Layers. Don't let that confuse you, it's rather a simple process.
Creating the Layer
First up, we have to create and zip the package. Go to your local terminal and type in the commands below. That will create a requirements-package.zip
file in the packages folder with Redis installed.
Then, go back to the shortener
function on AWS and direct to Layers from the sidebar. Click on the Create layer and fill in the needed configuration and upload the requirements-package.zip
file, just similar to mine.
When the layer is created, we need to connect this layer to our shortener
function. Go to the Layers section of the function and click Add a layer button.
Now, we should be able to shorten the URLs. What remains is retrieving the long URL from the short_url
key and redirecting the browser to that URL. For that, we are going to create a redirector
lambda function.
Lambda Function for URL Redirection
The process of creating redirector
lambda is the same as described above. Here are the steps once again:
- Creating a lambda function named
redirector
from the Lambda dashboard. - Setting the environment variables.
- Typing in the code given just below.
- Creating a layer with the
requirements-package.zip
file. (We may use theredis-library-layer
again, requirements are the same in this case.) - Adding the layer to the lambda function.
Here's the main algorithm for the redirector lambda.
Just like that, our lambdas are all ready! Although this is functional, to make this URL shortener an accessible service, we have to find a way to run our lambdas. There are several ways to consume lambda functions, but for this implementation we'll use the AWS API Gateway.
Creating the API Gateway on AWS
First, head to API Gateway from the AWS Console. In the dashboard, click the Create API button and build a REST API. After doing the basic configuration, we have our API in seconds.
We then need to connect the API Gateway to our Lambda functions. In the resources section, go to Actions > Create Resource. Enter the resource name
and resource path
.
Then click on the /shortener
path in the Resources and head to Actions > Create Method > Select GET > Confirm. This part is pretty important, this configuration enables us to transfer the request data from the API Gateway to the Lambda functions. Make sure they're correct!
We have connected the shortener function to our API, so we can now shorten our URLs. However, we need the redirector
Lambda function connected to the API for our service to work. Click on the /
in the Resources, head to Actions > Create Resource.
Click on the /{short_url}
in the Resources section, then Actions > Create Method > Choose GET > Confirm.
Finally, our API is set up. The final step is deploying the API. Go to Actions > Deploy API > Create New Stage. Type in the necessary fields and deploy. We now have a public API. In the Stages section, you can see the public Invoke URL for your API.
There is a final task to do: triggering the Lambda Functions via the serverless-shortener-API
gateway.
Go to the shortener
Lambda function, within the Function overview section, click the Add Trigger button.
When you add the trigger to both of the functions, our public API and the Lambda functions are ready to consume. For the shortener
function, triggering URL path is as such:
<YOUR_INVOKE_URL>/shortener?short_url="<LONG_URL>"
To trigger the redirector
function, you'll need the response from the shortener
function. The triggering URL for the redirector
has the structure below:
<YOUR_INVOKE_URL>/<SHORT_URL_KEY>
When you click it or send an HTTP Request to it, you'll be redirected to your long URL. Actually, our service is ready, but we'll create a web interface as a bit of sparkle.
Creating the Web Interface and Handling Function Usage
We'll use HTML, Bootstrap and JavaScript for the frontend. When the user types in a URL and click the Shorten button, a url will be prompted, redirecting the user to the original website.
This is a rather simple website with a few elements. First, add the following line to the <head>
block of the HTML code in order to use the Bootstrap features.
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"/>
Within the <body>
block, we'll have the main HTML elements.
After adding the elements, only the data fetching from the API Gateway remains. We'll handle that with JavaScript. Before the end of the <body>
part, insert the URL fetching functionality. Don’t forget to replace <INVOKE_URL>
with the one from your AWS API Gateway.
Final Words and Project Improvements
We've implemented the main features for our serverless URL shortener project. I hope it has been a clear demonstration of creating Python Lambda functions and consuming them. I'll also have some suggestions for improving the project, if you'd like to keep working on this project.
- Setting a custom domain for the URL shortener. The
Invoke URL
given by AWS is rather complex. Since this project's main purpose was demonstrating AWS Lambda and Upstash Redis, I didn't want to make this post longer with it. But If you'd like you could change the URL to a simpler and shorter one from the AWS API Gateway. - Implementing Upstash Rate Limit for the API. I have used free tier services for this project, but if you intend to build an active and public service, you should consider setting up a request limit to avoid unexpected costs.
- Hosting this project on Vercel.
Thanks for reading.