DEV Community

Alex Khismatulin
Alex Khismatulin

Posted on

Redirecting requests to a country-specific URL on AWS with CloudFront and Lambda

Sometimes you need to be sure you show relevant content to visitors in different countries. Let's see how it can be done using Amazon Web Services.

Prerequisites

In this tutorial, we will implement location-based redirects for an app distributed via Amazon CloudFront. I will store specific files on Amazon S3 but it could be any storage or web server. Finally, we will use AWS Lambda service to check country codes and return an appropriate response.

I added three files to the S3 bucket. Each of them is responsible for a particular locale:
Alt Text

Each file from the bucket has its own CloudFront distribution with the WEB distribution method. It might not make sense while they point to the same S3 bucket but in a real-world app each distribution would point to a different domain.
Alt Text

Setting Up Lambda Function

Open up Lambda service, select the region you need and hit Create function. Now we need to configure a function and name it:
Alt Text

The only thing that worth to be mentioned is the function's execution role. If this is your first Lambda function for CloudFront, you need to create a new role. Select Basic Lambda@Edge permissions (for CloudFront trigger) from the Policy templates dropdown and insert a role name for future usages. I named it cloudfront_basic but it might be any name. The role is required to let Lambda know what service is going to use the function. Go ahead and save your function.

It's time to get your hands dirty! Put the following code into the editor:

exports.handler = async (event) => {
    const getCustomResponseWithUrl = url => ({
        status: '302',
        statusDescription: '302 Found',
        headers: {
            location: [{
                key: 'Location',
                value: url,
            }],
        },
    });

    const request = event.Records[0].cf.request;
    const headers = request.headers;
    let response = request;

    if (headers['cloudfront-viewer-country']) {
        const countryCode = headers['cloudfront-viewer-country'][0].value;
        switch (countryCode) {
            case 'GB': {
                // generate a redirect response to the United Kingdom distribution
                response = getCustomResponseWithUrl('https://d1zywwhn3ytw4t.cloudfront.net');
                break;
            }
            case 'US': {
                // generate a redirect response to the United States distribution
                response = getCustomResponseWithUrl('https://d3gf6cz8gf6db6.cloudfront.net');
                break;
            }
            default: {
                // don't change the incoming request
                break;
            }
        }
    }

    return response;
};
Enter fullscreen mode Exit fullscreen mode

All we need to do is to check if the country from the cloudfront-viewer-country header fits any of our conditions. If so, we need to generate a redirect response with a URL of the CloudFront distribution we want to redirect to. If not, just need to return the incoming request from the event object that is passed as the first argument to the handler function. Dead simple!

To make the function visible to CloudFront distributions we need to save it and publish a new version from the actions dropdown. Copy the function's ARN, it will be available in the top right corner. We'll need it a moment later.

Adding Lambda Function to CloudFront distributions

Now it's time to make CloudFront distributions use the function. Go to CloudFront and open the distribution we created for requests that don't meet any condition(not from UK or US in our case). Open the behaviors tab and click Create behavior. Put * into the path to make it work for each path for simplicity. For the real-world app, you can add a more complex path pattern.
Next, select Whitelist for the Cache Based on Selected Request Headers setting. In the Whitelist Headers input, add CloudFront-Viewer-Country to the whitelisted headers list. It will make CloudFront add the cloudfront-viewer-country header that we use in the Lambda function.
Alt Text

Finally, put the ARN of the Lambda function we copied and associate it with the Origin Request event:
Alt Text

We're all set! Save the behavior we created. Wait for the distribution to deploy and that's it:
Alt Text

Further reading

CloudFront x Lamda examples
CloudFront x Lamda requirements and restrictions
Lamda function logging
Create aliases for different lambda environments or setups
NOTE: Lambda aliases and environment variables are not supported by CloudFront

Top comments (0)