Problem
When you deploy a CloudFront S3-backed website, you can set a default document at the site’s root. But you cannot carry that behavior into subfolders related to the site. For instance:
/index.html - will be displayed when you go to http://domain.com
but:
/test/index.html - will not be displayed when you go to http://domain.com/test
Solution
To work around this issue you can use Lambda@Edege to alter the request URI to the origin to specifically request the default (index.html) document if a document is not specified. This post will show how to do that.
Credit
Some sites I used in setting this up for refernce were:
- AWS Blog - Implementing Default Directory Indexes in Amazon S3-backed Amazon CloudFront Origins Using Lambda@Edge
- Implementing Default Directory Indexes in Amazon S3-backed Amazon CloudFront Origins Using CloudFront Functions
Method
First create a new Lambda Function:
Then you need to create a role that has access to Lamda at edge:
The code for the function:
def lambda_handler(event, context):
request = event['Records'][0]['cf']['request']
old_uri = request['uri']
new_uri = old_uri
is_file = len(old_uri.split('.'))>1
if not is_file:
new_uri = f"{old_uri}{'' if old_uri[-1] == '/' else '/'}index.html"
request['uri']=new_uri
return request
This function is straightforward. It gets the Uri from the request, and if the request appears to include a filename, it returns the same Uri as part of the re-written request. If it does not, it will return the Uri and append /index.html.
After the function is written and deployed, it must be saved to a version. Cloudfront will require a versioned ARN.
To modify the distribution you need to edit the associated behavior as such:
That is really all there is to it. Once you save the behavior changes they will be deployed and now your website will respond with default documents in folders, just like it does at the top level.