Mastering URL Redirections with AWS CloudFront Functions

Struggling with URL redirections for your AWS-hosted website? If you’re using an S3 bucket as your origin, you might have noticed that S3 alone doesn’t support dynamic redirects via server-side rules. That’s where AWS CloudFront Functions come in—offering a fast, simple, and cost-effective way to manage redirections. In this guide, we’ll show you how CloudFront can handle your URL redirections without requiring separate S3 buckets or CloudFront distributions, streamlining your architecture and improving your website’s SEO and user experience.

1. Introduction

URL redirection is essential for seamless navigation and improved SEO. When using S3 as a static website origin, implementing complex redirects directly through file configurations is not possible. AWS CloudFront Functions allow you to handle dynamic redirects at the edge, solving this limitation and removing the need for additional S3 buckets or separate CloudFront distributions just for redirection purposes.

Real-World Example: awsgem.com

A diagram illustrating an AWS architecture, with a client connected to Edge Locations, CloudFront Edge Caches, CloudFront Regional Edge Caches, CloudFront Functions, and an Origin S3 Bucket.

At awsgem.com, we faced challenges in managing URL redirections using S3 as the origin. We needed to efficiently handle traffic between www.awsgem.com and awsgem.com while maintaining clean URLs by redirecting paths like /canarycalc/ to /canarycalc/index.html without the need for multiple S3 buckets or CloudFront distributions.

By implementing CloudFront Functions, we achieved:

  • Efficient Subdomain Redirection: Redirected traffic between www and non-www domains without needing an extra S3 bucket or distribution.
  • Optimized Performance: Offloaded the redirection logic to CloudFront, reducing latency and server load.

2. The Challenges of URL Redirection

Common redirection challenges include:

  • Subdomain Redirection: Redirecting between www and non-www versions to avoid duplicate content, boost SEO, and maintain consistent branding.
  • Directory Handling: Redirecting paths like /canarycalc/ to /canarycalc/index.html to serve content correctly.

3. CloudFront Functions: Edge Computing Made Simple

CloudFront Functions, introduced by AWS in 2021, are a game-changer for handling lightweight edge computing tasks. They provide an efficient way to execute JavaScript code at the edge, closer to the end-user.

Key Advantages

  • Ultra-Low Latency: Executes in sub-millisecond timeframes
  • Cost-Effective: Pay only for the compute you use, with a generous free tier
  • Simplified Development: Write in JavaScript, deploy directly within CloudFront
  • Global Scale: Automatically deployed to all CloudFront edge locations worldwide
  • Stateless Execution: Designed for quick, contextual operations without need for external data

Use Cases

  • Implementing custom URL redirection logic
  • Normalizing query strings for improved caching
  • Adding or modifying HTTP headers for security or analytics purposes

Limitations

  • Limited to JavaScript
  • Maximum execution time of 1ms
  • No access to external services or databases

CloudFront Functions excel at tasks that require speed and simplicity, making them an ideal solution for many edge computing scenarios.

4. Breaking Down the CloudFront Functions Code

Below are two separate examples for managing non-www to www and www to non-www redirections, as well as handling clean URL redirection (e.g., /about/ to /about/index.html).

Example 1: Redirecting non-www to www

function handler(event) {
    var request = event.request;
    var headers = request.headers;
    var uri = request.uri;

    // Redirect non-www to www
    if (headers.host && !headers.host.value.startsWith('www.')) {
        var host = 'www.' + headers.host.value;  // Add 'www.'
        var location = 'https://' + host + uri;
        return {
            statusCode: 301,
            statusDescription: 'Moved Permanently',
            headers: {
                'location': { 'value': location },
                'strict-transport-security': { 'value': 'max-age=31536000; includeSubDomains; preload' },
                'x-content-type-options': { 'value': 'nosniff' },
                'x-frame-options': { 'value': 'DENY' },
                'x-xss-protection': { 'value': '1; mode=block' }
            }
        };
    }

    // Redirect to /index.html for directories
    if (uri.endsWith('/') || !uri.includes('.')) {
        request.uri = uri.replace(/\/?$/, '/index.html');
    }

    return request;
}

Example 2: Redirecting www to non-www

function handler(event) {
    var request = event.request;
    var headers = request.headers;
    var uri = request.uri;

    // Redirect www to non-www
    if (headers.host && headers.host.value.startsWith('www.')) {
        var host = headers.host.value.substring(4);  // Remove 'www.'
        var location = 'https://' + host + uri;
        return {
            statusCode: 301,
            statusDescription: 'Moved Permanently',
            headers: {
                'location': { 'value': location },
                'strict-transport-security': { 'value': 'max-age=31536000; includeSubDomains; preload' },
                'x-content-type-options': { 'value': 'nosniff' },
                'x-frame-options': { 'value': 'DENY' },
                'x-xss-protection': { 'value': '1; mode=block' }
            }
        };
    }

    // Redirect to /index.html for directories
    if (uri.endsWith('/') || !uri.includes('.')) {
        request.uri = uri.replace(/\/?$/, '/index.html');
    }

    return request;
}

Code Breakdown:

  • Subdomain Redirection: Each function example separately handles redirection between www and non-www domains. This eliminates the need for creating extra S3 buckets or distributions, simplifying your architecture while ensuring consistency for users and search engines.
  • Directory Handling: Automatically appends /index.html to directory requests like /about/ so content is served correctly.

Advanced Use Cases:

  • Retain Query Parameters: If query parameters (e.g., ?utm_source=google) are present, ensure they are retained during redirection:

    var querystring = request.querystring ? '?' + request.querystring : '';
    var location = 'https://' + host + uri + querystring;
    
  • Path-Based Redirects: Implement custom path-based redirects by checking for specific URIs:

    if (uri.startsWith('/old-path')) {
        return {
            statusCode: 301,
            statusDescription: 'Moved Permanently',
            headers: {
                'location': { 'value': 'https://' + host + '/new-path' }
            }
        };
    }
    

5. Step-by-Step Implementation

  1. Create an S3 Bucket as the Origin: Store your website files in an S3 bucket with static web hosting enabled.
  2. Set Up CloudFront: Create a CloudFront distribution with your S3 bucket as the origin.
  3. Add a CloudFront Function: Create separate CloudFront Functions for either non-www to www or www to non-www redirection, depending on your preference. Paste the respective code into each function. A screenshot of the AWS CloudFront console, showing a specific function named “RedirectWWWToNonWWW”. The function code is displayed, which redirects HTTP requests from a URL with “www.” in the host header to a URL without “www.”. Other details about the function, such as its development runtime, ARN, and last modified time, are also shown.
  4. Deploy: Associate the function with the “Viewer request” event in your CloudFront distribution.

6. Testing and Validation

Test your redirections:

  • Visit yourdomain.com to confirm it redirects to www.yourdomain.com, or vice versa depending on your setup.

  • Access www.yourdomain.com/about/ and verify that /about/index.html is served correctly.

  • Test with various paths and query parameters to ensure they’re handled correctly.

  • Use online redirect checkers to verify your setup from different locations. for example: https://www.redirect-checker.org/

  • Or using curl

    curl -I -L http://example.com

A terminal window displaying the output of a curl command, showing HTTP requests and responses with details like status codes, headers, and content information. The response indicates that the request was redirected from the root URL to the / URL and then served a static HTML page from CloudFront.

7. Troubleshooting

Redirect Loops:

  • Issue: Endless redirection between www and non-www versions.
  • Solution: Ensure your origin (S3 or web server) isn’t also performing conflicting redirects. Check your S3 bucket settings and any .htaccess files if applicable.

Function Errors (HTTP 500):

  • Issue: CloudFront returns a 500 error when the function is triggered.
  • Solution:
    1. Check the CloudFront console for logs and error messages.
    2. Use the “Test” feature in the CloudFront Functions console to debug your code.
    3. Adjust the logic, especially around headers or query parameters.

Cache Invalidation:

  • Issue: CloudFront caches incorrect redirects.
  • Solution:
    1. Use cache invalidation to refresh edge nodes.
    2. Adjust cache-control headers if necessary to avoid unintended caching.
    3. Consider setting a low TTL for your distribution during testing.

8. CloudFront and Cost Considerations

CloudFront Functions are highly economical, especially with the free tier covering 2,000,000 invocations monthly. Beyond the free tier, the cost remains minimal at $0.01 per 1,000,000 invocations. This makes CloudFront Functions an excellent choice for handling URL redirections and reducing server load without the need for extra resources.

9. SEO Impact of Proper Redirection

Proper URL redirection helps:

  • Avoid Duplicate Content: Ensures that search engines don’t penalize your site for having duplicate content across www and non-www versions.
  • Preserve Link Equity: Redirecting outdated URLs preserves the SEO value of incoming links.
  • Enhance Crawl Efficiency: Search engines can better understand your website’s structure, leading to faster indexing and ranking improvements.

10. Comparison with Alternative Solutions

Feature CloudFront Functions Lambda@Edge Traditional Server-Side Redirects (Not Applicable with S3 Origin)
Execution Speed < 1ms 5-50ms Variable (typically slower)
Cost Very Low Low-Medium Depends on server resources
Complexity Low Medium Varies
Customization Limited High High
Scalability Automatic
10,000,000 requests per second or more
Automatic
Up to 10,000 requests per second per Region
Manual
Depends on server resources
Can build and test entirely within CloudFront Yes No No
Cold Starts No Yes N/A

11. Conclusion

CloudFront Functions provide a fast, cost-effective solution for handling URL redirections without needing additional S3 buckets or CloudFront distributions. This approach enhances your site’s performance, simplifies architecture, and improves SEO. By implementing the strategies outlined in this guide, you can efficiently manage redirections, improve user experience, and optimize your AWS-hosted website.

12. Further Reading

Have you implemented this solution? We’d love to hear about your experiences or any unique challenges you’ve faced. Reach out on Linkedin!

Similar Posts You Might Enjoy

Enhancing CloudFront Security with Response Headers

Response headers play a vital role in reinforcing security measures, protecting against various attacks, and enhancing the overall security of your web applications. In this blog post, we’ll explore how to implement a CloudFront response header policy to improve security, walk through the process of testing and refining your settings, and discuss how to automate these changes across your infrastructure. - by Alexey Vidanov

AWS Cost Management Made Easy: Build Your Own Calculator with the AWS Pricing API

When discussing AWS pricing with customers, limitations in the official AWS Pricing Calculator can sometimes hinder accurate cost estimations. This blog post addresses a specific challenge encountered with AWS CloudWatch Synthetics pricing and provides a solution by building a custom calculator using the AWS Pricing API. - by Alexey Vidanov

Harnessing the Power of Serverless PHP with Laravel Vapor

I need to start this blog post with a confession. But only if you promise to not tell anything to my tecRacer colleagues, deal? So, I built a monolith. And I loved it. And you will likely love it too if you decide to try out Laravel. Luckily, there is a service called Vapor that will let you deploy your Laravel project on serverless AWS infrastructure. That means I can continue to enjoy the top-notch developer experience of Laravel while also getting all the benefits of serverless technologies (plus, I can maintain a healthy relationship with my colleagues 🎉). But let’s start at the beginning. - by Leon Bittner