π Fixing CloudFront "Forbidden" Errors with CloudFront Functions: Auto-Redirect Any Folder Path to index.html
π Introduction
Have you hosted a static website on AWS CloudFront with an S3 private bucket and faced this issue?
β
https://yourdomain.com/random-page/index.html
β Works
β https://yourdomain.com/random-page
β Forbidden (403 Error)
β https://yourdomain.com/random-page/
β Forbidden (403 Error)
This happens because CloudFront does not automatically append index.html
when accessing directories. But don't worry! In this guide, weβll troubleshoot the issue and fix it using CloudFront Functionsβwithout changing your file names.
π οΈ Understanding the Issue
π Why does this happen?
AWS S3 is an object storage service, not a traditional web server. Unlike Apache or Nginx, S3 does not recognize directoriesβit only sees files.
When you request
https://yourdomain.com/random-page
, CloudFront searches for an object named exactlyrandom-page
, which does not exist.But when you request
https://yourdomain.com/random-page/index.html
, the file exists in S3, so CloudFront serves it correctly.Unlike traditional web servers, CloudFront does not automatically append
index.html
to folder paths.
πΉ Goal: We need to make https://yourdomain.com/ANYTHING
and https://yourdomain.com/ANYTHING/
automatically redirect to index.html
.
π οΈ Solution: Fix Routing with a CloudFront Function
The best way to fix this issue is by using CloudFront Functions. These are lightweight, JavaScript-based functions that run at CloudFront Edge Locations.
π Why Use CloudFront Functions?
β
Fast Execution β Runs at CloudFront Edge, reducing latency
β
Cost-Effective β Cheaper than AWS Lambda@Edge
β
Scalable β Handles millions of requests per second
β
No Changes in S3 Required β Fix the issue at CloudFront level
πΉ Use Cases for CloudFront Functions:
Rewrite URLs dynamically (e.g., auto-append
index.html
)Redirect HTTP to HTTPS
Add security headers
Block unwanted traffic
Now, letβs implement the solution! π
πΉ Step 1: Create a CloudFront Function
1οΈβ£ Go to AWS CloudFront Console
Open the AWS CloudFront Dashboard
Click on Functions β Create function
Name it
"RewriteToIndexHtml"
Click "Create function"
2οΈβ£ Add the following JavaScript code
function handler(event) {
var request = event.request;
var uri = request.uri;
// If the URL does not contain a file extension, append "index.html"
if (!uri.includes('.') && !uri.endsWith('/')) {
request.uri += '/index.html';
}
else if (uri.endsWith('/')) {
request.uri += 'index.html';
}
return request;
}
π Explanation of CloudFront Function Code
This CloudFront Function modifies incoming requests to ensure folder paths correctly serve index.html
.
1οΈβ£ Checks if the URL (uri
) has a file extension (.
) or ends with /
If no file extension and no trailing
/
, appends"/index.html"
If trailing
/
exists, appends"index.html"
2οΈβ£ Returns the modified request so CloudFront fetches the correct file from S3.
β
Ensures URLs like yourdomain.com/about
correctly load yourdomain.com/about/index.html
. π
3οΈβ£ Save and Publish the Function
Click Save
Click Publish
πΉ Step 2: Attach the Function to Your CloudFront Distribution
1οΈβ£ Go to Your CloudFront Distribution
Click on Distributions β Select your CloudFront distribution
Go to the Behaviors tab
Click Edit on the behavior for your S3 origin
2οΈβ£ Attach the Function
Scroll down to "Function Associations"
Under "Viewer Request", select the function you just created (
RewriteToIndexHtml
)Click Save Changes
πΉ Step 3: Invalidate CloudFront Cache
Since CloudFront caches content, you need to invalidate the cache to apply the new routing logic.
πΉ Run this command in AWS CLI:
aws cloudfront create-invalidation --distribution-id YOUR_DISTRIBUTION_ID --paths "/*"
Now CloudFront will fetch fresh content and apply the function.
π― Final Testing: Does It Work?
User Requests | Before Fix (403 Error) | After Fix (200 OK) |
https://yourdomain.com/ | β Forbidden | β
/index.html |
https://yourdomain.com/random-page | β Forbidden | β
/random-page/index.html |
https://yourdomain.com/random-page/ | β Forbidden | β
/random-page/index.html |
https://yourdomain.com/any-folder-name | β Forbidden | β
/any-folder-name/index.html |
π Now your website behaves like a normal static site! π
π Use Case: When Should You Use This?
πΉ Hosting a static website with S3 + CloudFront where you need directory-style URLs (/page
instead of /page/index.html
).
πΉ Avoiding unnecessary redirects or renaming files in S3.
πΉ Improving SEO and user experience by allowing clean URLs without .html
.
πΉ Reducing costs by using CloudFront Functions instead of Lambda@Edge.
π‘ Key Takeaways
β
CloudFront does not automatically serve index.html
when accessing folder paths.
β
S3 is object-based storageβit does not recognize directories, only files.
β
A CloudFront Function can rewrite URLs dynamically to fix this issue.
β
No need to rename files or change S3 storage structure.
β
CloudFront Functions are fast, scalable, and cost-effective compared to Lambda@Edge.
π Final Thoughts
This simple fix allows CloudFront to behave like a traditional web server, automatically loading index.html
for subpages without renaming files in S3!
If you found this helpful, share this blog and let me know your thoughts in the comments! π¬π
β¨ Need More AWS & DevOps Tips?
Follow me for more AWS, DevOps, and Cloud solutions! ππ