- Published on
URI Redirects with CloudFront Functions
Part 6 of "Deploy Static Website To AWS"
Table of Contents
Overview
The Problem
Although navigation works well within the next.js application, refreshing the webpage or navigating directly to a path (e.g example.com/path/to/page
) results in a 404 Not Found error. Alternatively, it may redirect to based on the error codes as defined in the distribution config.
When adding .html
to the end of the path (e.g example.com/path/to/page.html
), the navigation works as expected.
The Goal
One solution to rectify this is to simply modify the request object adding .html
at the end of every page. CloudFront Functions is used to receive incoming request and decide whether .html
needs to be added to the path before passing the request on. Lambda@Edge functions could also be used, however is slower and more expensive. Here is a good article comparing CloudFront functions and Lambda@Edge.
Implementation
AWS Console
Create the Function
Create the function in CloudFront > Functions
.
Specify the name and description and define the request transformation behavior. In this instance, .html
(if not already present) is appended to any page. We also need to ensure that requests for other content are not altered. In the below example, the path of these request start with /static
and /_next
, and should not be altered.
function handler(event) {
var request = event.request;
var uri = request.uri;
if (uri.startsWith("/static") || uri.startsWith('/_next') || uri.endsWith('.html')) {
return request;
}
request.uri += '.html';
return request;
}
Ensure that any changes are saved
Test
Once the function code is saved, test the function by trying different paths to ensure all requests are handled.
Publish
Once tested, publish the function
Link the Function to the Distribution
Link the distribution behavior to the new function by editing the behavior in CloudFront > Distributions > Distribution > Behaviors
Associate the function. Ensure that the function is added to the viewer request
Once added, visit the webpage in different browsers and devices to ensure that cached copies are not being returned. The function code may need to be updated based on the specific path requirements.
Infrastructure as Code
The following will be added to the existing infrastructure pipeline see Part 3B.
Define CloudFront Function
See the CloudFormation config for more information.
# serverless.yml
resources:
Resources:
# ...
RedirectFunction:
Type: AWS::CloudFront::Function
Properties:
AutoPublish: true
FunctionCode: >
function handler(event) {
var request = event.request;
var uri = request.uri;
if (uri.startsWith("/static") || uri.startsWith('/_next') || uri.endsWith('.html')) {
return request;
}
request.uri += '.html';
return request;
}
FunctionConfig:
Comment: 'Ensure .html is appended to page paths'
Runtime: cloudfront-js-1.0
Name: "redirectFunction"
Link Function to Distribution
# serverless.yml
resources:
Resources:
# ...
WebAppCloudFrontDistribution:
# ...
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
DefaultCacheBehavior:
FunctionAssociations:
- EventType: viewer-request
FunctionARN: !GetAtt RedirectFunction.FunctionMetadata.FunctionARN