CloudFront Edge Computing - Dynamic At Edge with CloudFront Functions
Tags: aws, cloudfront, cdn
Published: 2023-08-14 06:53:53

Edge Computing feature is definitely one of the things that I like the most with CloudFront service. When [CloudFront Functions](https://aws.amazon.com/blogs/aws/introducing-cloudfront-functions-run-your-code-at-the-edge-with-low-latency-at-any-scale/) is launched, it makes the feature even better. 

Recently I saw someone asked a question about the following scenario in [re:Post](https://repost.aws/questions). I think it is a perfect scenario for CloudFront Functions.

Files in the S3 origin: 
- JSON files are under content folder(prefix), e.g. s3://example_bucket/content/a.json
- Image files are under a sub-folder of content folder (prefix) e.g. s3://example_bucket/content/image/a.png

The files are requested by viewer request like:
- JSON file: https://text.example.com/abc/a.json
- PNG file: https://image.example.com/a.png

What is going to happen when there was no edge computing in CloudFront service? 

For the JSON file, there might be no other options but move the objects under 'content/abc/' folder. Then origin path will be 'content/' in origin setting of the distribution.

For the PNG file, it will require a separate origin setting in the distribution configuration other than the JSON file because they are not going to share the same origin path. The PNG file will need origin path as 'content/image'.

The JSON file and PNG files will also need different behaviors because they need to call different origin settings.

It looks like lots of work. 

With CloudFront Functions, a few lines of codes will resolve the problem. 

```
function handler(event) {
    var request = event.request;
    var uri = request.uri;
    var file_name = uri.split('/').pop();

    // Check whether the URI is missing a file name.
    if ( file_name.endsWith('.json')) {
        request.uri = "/content/" + file_name;
        return request;
    } else if (file_name.endsWith('.png')) {
        request.uri = '/content/image/' + file_name;
        return request;
    }

    return request;
}
```
In the behavior, the function will be added as Viewer Request trigger in Default behavior with an S3 origin pointing to "s3://example_bucket". 

That is it! 

And if any further requirement is required, e.g. changing path based on the requesting domain name, only a few modifications in codes will meet the requirement.

```
function handler(event) {
    var request = event.request;
    var uri = request.uri;
    var file_name = uri.split('/').pop();
    var host = request.headers.host.value;

    // Check whether the URI is missing a file name.
    if ( host === "text.example.com" ) {
        request.uri = "/content/" + file_name;
        return request;
    } else if ( host === "image.example.com" )) {
        request.uri = '/content/image/' + file_name;
        return request;
    }

    return request;
}
```

CloudFront Functions are perfect to process those 'small' modifications in viewer requests and responses. 

The code I am using is modified from this [code example](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/example-function-add-index.html) in CloudFront public document.

I am seeing a trend that generative AI tools like ChatGPT or Amazon CodeWhisperer will help to writ those scripts much easier than ever! 

Like Lambda@Edge, there are some [restrictions](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/functions-javascript-runtime-features.html) on runtime of CloudFront Functions that you should have a read before wring your codes.