Build a Serverless, Private URL Shortener
As a solutions architect, I often need to send large files to customers, such as architecture diagrams and service presentations. To avoid sending heavy attachments in email, I first upload the content on Amazon S3, then send a pre-signed URL to allow the customer to securely download the content. However, S3 pre-signed URLs are generally over 250 characters and may be split in several lines by email clients. It’s more convenient and user-friendly to generate a shortened URL. As this content is often confidential, I tend to avoid using public URL shortener services. This is when I realized it was super easy to build a private one.
In this post, you’ll see how to build your own private URL shortener using a serverless architecture, which leaves you with full control over your application while leveraging managed AWS services like AWS Lambda, AWS API Gateway, and S3. Because you don’t need to manage your own servers anymore, it’s easy to build applications that are natively scalable, secure, resilient, and very cost effective.
The following graphic shows the admin page.
This next graphic shows a generated short URL ready to copy and paste.
Using the redirection engine
It’s a little known feature: S3 can act as a redirection engine.
First, you need to activate “website hosting” on your S3 bucket. Then you create an empty object for each short URL (a random 5-character ID) and attach the “website redirect” metadata with the target (long) URL. When the end user hits the short URL, S3 automatically responds with a HTTP redirect to the target (long) URL, without you needing any code. For more information, see Configuring a Web Page Redirect.
To avoid proliferation of these redirect objects, you can enable a lifecycle policy to automatically delete objects, for example, after 7 days.
Creating an admin page
In order to create redirection objects, you need a simple admin page: a static HTML page hosted in S3 and built with jquery. When you choose Shorten , it triggers a POST request to API Gateway, which securely invokes a Lambda function (~70 lines of code) after validating all parameters. The code in Lambda simply stores an empty object in S3 with a random 7-character name, and assigns the metadata for the HTTP redirect.
Using Amazon CloudFront to wrap everything together
To avoid CORS configuration and have a simple friendly domain name, wrap all pieces behind a single Amazon CloudFront distribution as shown in the diagram below. There are three CloudFront actions:
- All requests for the “/admin/” prefix serve static HTML files from S3.
- All requests for the “/prod/” prefix are sent to API Gateway.
- All other requests are served from S3 from a specific folder named “u” that stores all redirection objects.
Here’s a diagram of the process.
Build your own – a step by step guide
The CloudFormation template below creates all components for the URL shortener: S3 bucket, Lambda functions, API Gateway API operation, and Amazon CloudFront distribution.
- Choose Next and enter the following parameters:
- For Stack name , enter “URLShortener”.
- For S3BucketName , enter the name of your new S3 bucket or leave this field blank to have a name automatically generated.
- For URLExpiration , enter 7 (the number of days before the short URLs are automatically deleted).
- Choose Next , Next , Acknowledge the creation of IAM resources , and then Create.
- The stack takes ~20 minutes to complete. Choose the CloudFormation Outputs tab. The ConnectURL field shows the URL to be used.
Note: the template creates three Lambda functions: The LambdaShortener-xxx function contains the main code and the other two functions, LambdaURLtoDomain-xxx and LambdaS3Copy-xxx, are helper functions used as CloudFormation custom resources.
Architecture and cost considerations
Using a full serverless application has several benefits: the application is natively multi-AZ and automatically scales whether you have one request per month or tens per second.
Now evaluate the cost of the URL shortener for a simple scenario: You create 1000 short URLs per month and each is viewed by 1000 users – i.e., 1 million requests per month. Here is a cost estimate for the Oregon region split by services:
- –Lambda: 1000 invocation each of less than 1 second – less than $0.003 / month
- –API Gateway: 1000 API calls – less than $0.004 / month
- –S3: storage cost is negligible, cost for 1 million GET is $0.04 / month
- –Amazon CloudFront: bandwidth cost is negligible, cost for 1 million GET is $0.075 / month
The overall cost is less than 12 cents per month.
This simple version is the starting point to your creativity. There are many ways you can improve this simple version, for example:
- Set up your own custom DNS domain name. Leverage services like AWS Route 53 and AWS Certificate Manager to set up your own CloudFront custom domain name and SSL Certificate.
- Analyze logs: Amazon CloudFront already provides report and analytics tools. If you want to use alternative tools, activate Logging in your CloudFront distribution and feed logs to your favorite analytics tool or serverless data-store like Amazon DynamoDB or Amazon ElasticSearch Service.
- Set up access control to the admin page: use serverless solutions like Amazon Cognito or use Custom Authorizers in API Gateway
Please send us your comments and ideas.