Customising Content Delivery with AWS CloudFront: Routing with Origin Request Policies and CloudFront Functions

gritcoding

Grit Coding

Posted on April 18, 2024

Customising Content Delivery with AWS CloudFront: Routing with Origin Request Policies and CloudFront Functions

While studying for the AWS SysOps Administrator certification exam, I discovered an interesting feature in AWS CloudFront that allows serving different objects based on cookies or HTTP request headers specified through the origin request policy. This concept intrigued me, but it didn’t truly resonate until I began experimenting with it myself. In today’s blog post, I will share a step-by-step guide on how to set this up by forwarding the value of request headers. To enhance clarity, I'll conclude with a visual demonstration directly from the AWS console.

This post is intended for readers with existing knowledge of AWS.

Prerequisites

  • Knowledge of S3 Buckets & Policies
  • Understanding of how to set up a CloudFront Distribution with S3

Image description

By creating a CloudFront distribution as shown above, you can access https://d3h4a6v5efbkjq.cloud.net/index.html directly, leads you to index.html without any prefix.

Image description

We will forward the Accept-Language header, and the CloudFront function will then redirect based on this value. For example, if the Accept-Language value is English, the user will be redirected to /en/index.html.

Create S3 Bucket and Upload Files

Navigate to S3 from the AWS console and create a new bucket.
Set up your project files as follows:
Root directory: index.html
Korean version: /kr/index.html
English version: /en/index.html



<!-- Root index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>gritcoding</title>
    <meta charset="UTF-8">
</head>
<body>
    <h1>gritcoding</h1>
</body>
</html>

<!-- /kr/index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>한국어</title>
    <meta charset="UTF-8">
</head>
<body>
    <h1>안녕</h1>
</body>
</html>

<!-- /en/index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>English</title>
    <meta charset="UTF-8">
</head>
<body>
    <h1>hi</h1>
</body>
</html>



Enter fullscreen mode Exit fullscreen mode

Once uploaded, you will be able see index.html, /en/index.html, /kr/index.html objects in the bucket.

Image description

Create CloudFront Function and Deploy

Navigate to CloudFront and crate a new function.
Image description
Update the function using the code below.



function handler(event) {
    const request = event.request;
    const headers = request.headers;

    // Check for English language in Accept-Language header
    const langHeader = headers['accept-language'];
    if (langHeader && langHeader.value.indexOf('en') !== -1) {
        // Route to English version of the content
        request.uri = '/en' + request.uri;
    } else {
        // Route to Korean version of the content
        request.uri = '/kr' + request.uri;
    }

    return request;
}


Enter fullscreen mode Exit fullscreen mode

Now, you can test this function in the test tab. Use the following steps to simulate a request.

  • Scroll down to the Add header button and click it.
  • Enter accept-language as the header key.
  • Add en-GB as the header value.
  • Click the Test function button located above. If the test is successful, you should see that it returns /en/index.html as shown in the screenshot below.

Image description

Create CloudFront Origin Request Policy

Navigate to CloudFront/Policies/Origin request as shown in the screenshot below.

Image description

Name the policy, select include the following headers in the Headers dropdown, and choose the Accept-Language header.

Image description
Once the origin request policy is created, proceed to create a distribution.

Create CloudFront Distribution

Navigate to CloudFront and click the create distribution button. Select the bucket you created as the Origin domain.
Then, scroll down to the Cache key and origin requests section, select the origin request policy you created, and set the viewer request function type to CloudFront functions to select the function we created.

Image description

Update S3 Bucket Policy

Navigate back to your S3 bucket and update the bucket policy.
Use the following JSON code to update it, ensuring you replace S3 bucket name, Your AWS Account Number, and CloudFront distribution ID with the actual values specific to your setup.



{
    "Version": "2012-10-17",
    "Statement": {
        "Sid": "AllowCloudFrontServicePrincipalReadWrite",
        "Effect": "Allow",
        "Principal": {
            "Service": "cloudfront.amazonaws.com"
        },
        "Action": "s3:GetObject",
        "Resource": "arn:aws:s3:::<S3 bucket name>/*",
        "Condition": {
            "StringEquals": {
                "AWS:SourceArn": "arn:aws:cloudfront::<Your AWS Account Number>:distribution/<CloudFront distribution ID>"
            }
        }
    }
}


Enter fullscreen mode Exit fullscreen mode

After updating the policy, copy the CloudFront distribution domain name and paste it into your web browser followed by /index.html. Depending on the Accept-Language header in your request, this setup will either direct you to /en/index.html if English is detected, or /kr/index.html for all other languages.
Image description
In this setup, direct access to the index.html with the gritcoding message is not available, as the CloudFront distribution has been configured to redirect based on language settings.

Learn more:

Watch the step-by-step video guide on setting up and testing this configuration on our YouTube channel linked below.

Thanks for reading. :)

💖 💪 🙅 🚩
gritcoding
Grit Coding

Posted on April 18, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related