Default root object

If you define a default root object, end user requests for a subdirectory of your distribution do not return the default root object. For example, suppose index.html is your default root object and CloudFront receives an end user request for the install directory under your CloudFront distribution.:

https://d111111abcdef8.cloudfront.net/install/

CloudFront does not return the default root object even if a copy of index.html appears in the install directory.

At this point an empty resource is downloaded as a file

This is significantly different from the usual nginx directory access


Implementing nginx-like behavior

The following example function appends index.html to requests that do not include a file name or extension in the URL. This function is useful for single-page applications or statically generated websites hosted in an Amazon S3 bucket.

View this example on GitHub

function handler(event) {
    var request = event.request;
    var uri = request.uri;

    // Check whether the URI is missing a file name.
    if (uri.endsWith('/')) {
        request.uri += 'index.html';
    }
    // Check whether the URI is missing a file extension.
    else if (!uri.includes('.')) {
        request.uri += '/index.html';
    }

    return request;
}

For example, if a user visits www.example.com/blog, the actual file in S3 is stored at /blog/index.html. In order for CloudFront to direct the request to the correct file in S3, you need to rewrite the URL to www.example.com/blog/index.html before getting the file from S3. This function intercepts incoming requests to CloudFront and checks for the presence of a file name and extension. If there is no file name and extension, or if the URI ends with “/”, the function appends index.html to the URI.

There is a feature in CloudFront called the Default Root Object that allows you to specify an index document that applies only to the root object and not to any subfolders. For example, if you set index.html as the default root object and a user visits www.example.com, CloudFront automatically rewrites the request to www.example.com/index.html. However, if the user visits www.example.com/blog, this request is no longer in the root directory, so CloudFront does not rewrite this URL and sends it to the origin as is. This function handles URL rewriting for the root directory and all subfolders. Therefore, you do not need to set a default root object in CloudFront when using this feature (although it doesn’t hurt to set it)

Note: If you are using S3 static website hosting, you do not need to use this feature. S3 static website hosting allows you to set up an index document. The index document is the web page that Amazon S3 returns when any request lacks a file name, whether it is for the root directory of your website or a subfolder. This Amazon S3 feature performs the same operation as this one.


Really implement the same behavior as nginx

Is the above implementation of nginx behavior? It is not really implemented. It is OK for single-page applications, but it cannot correctly handle the access path for richer resources

Nginx directory access behavior: For example, http://www.abc.com/abc, the server will search for a file or directory named abc in the root directory of the website. If it is a directory, the server will return a 301 redirect, and the browser will use http://www.abc.com/abc/ to access

And the behavior of the above function: For example, http://www.abc.com/abc, the cloudfront function directly modifies the request to http://www.abc.com/abc/index.html to get the resource and return

Do you see the difference from the above? The browser initiates a second request to access the nginx server, so its relative path is /abc/, while for cloudfront, the browser will always think it is under ‘/’, so the subsequent request uris are different.

function handler(event) {
    var request = event.request;
    var headers = request.headers;
    var host = request.headers.host.value;
    var uri = request.uri;

    // Check whether the URI is missing a file name.
    if (uri.endsWith('/')) {
        request.uri += 'index.html';
    }
    // Check whether the URI is missing a file extension.
    else if (!uri.includes('.')) {
        var newuri = uri + '/'
        var newurl = `https://${host}${newuri}` // Change the redirect URL to your choice
        //var newurl = request.url + '/index.html'

        var response = {
            statusCode: 301,
            statusDescription: 'Found',
            headers:
                { "location": { "value": newurl } }
        }
         return response;
    }

    return request;
}

When the URL path is a directory and does not end with ‘/’, the browser is directly returned with response 301

See Redirecting viewers to a new URL

Last modified: July 16, 2025

Comments

Write a Reply or Comment

Your email address will not be published.