Jekyll Site hosted on Amazon S3

We have an issue regarding the hosting of our Jekyll sites on Amazon S3. We would like to be able to access, for example, the /about/index.html page via /about/ and /about ( so the generated folder name with an without a trailing slash). The webserver is stored on S3, and hosted via the S3 URL `site-name.s3-website-us-east-1.amazonaws.com’ cached via CloudFront. CloudFront caches the redirect, not the target of the redirect, so we can’t rely on the 302 to do the work. So far we have had no luck with getting this to work other than manually adding redirect objects for the desired paths etc. Does anyone on here have a way to get this working on any ideas surrounding this issue?

Many Thanks

Kyle @Linaro

Hi, kylekirkby.

Please check your CloudFront settings for “Restrict Bucket Access”.
If you set “No”, CloudFront is able to return a root object (index.html) of subdirectory.

Be sure, “Origin Domain Name” should be “site-name.s3-website-us-east-1.amazonaws.com”, NOT “site-name.s3.amazonaws.com”.

Please see the AWS document.

When you define a default root object, an end-user request that calls the root of your distribution returns the default root object. For example, if you designate the file index.html as your default root object, a request for:

http://d111111abcdef8.cloudfront.net/

returns:

http://d111111abcdef8.cloudfront.net/index.html

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

http://d111111abcdef8.cloudfront.net/install/

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

Thanks for the reply! All of the above is working. It is only when we omit the trailing slash does the behaviour not work as expected. For example /about should go to /about/.

Many Thanks,

Kyle

My understanding is that S3 can only serve without the trailing slash if you rename all your files and omit the .html - so if you have a file named about and it has no extension, and it is an html file, it should be able to serve it and there will be no trailing slash or extension. There is no real way to accomplish this easily so I have not seen anyone do it. All my S3 urls have a trailing slash.

Keep in mind that S3 is not a server - it is a storage manager with the ability to serve files.

Also, I would think from a google search standpoint that you would not want both /about/ and /about to work - seems like they would be dupe urls?

rdyar is correct.
I’m sorry I can’t help you.

If you create such a folder structure in your bucket, you must have an index document at each level. When a user specifies a URL that resembles a folder lookup, the presence or absence of a trailing slash determines the behavior of the website. For example, the following URL, with a trailing slash, returns the photos/index.html index document.

http://example-bucket.s3-website-region.amazonaws.com/photos/

However, if you exclude the trailing slash from the preceding URL, Amazon S3 first looks for an object photos in the bucket. If the photos object is not found, then it searches for an index document, photos/index.html. If that document is found, Amazon S3 returns a 302 Found message and points to the photos/ key. For subsequent requests to photos/, Amazon S3 returns photos/index.html. If the index document is not found, Amazon S3 returns an error.

One way of solving this problem is by setting up a CloudFront function to redirect requests. I have the following function below set up for my site. One hole with this solution is that if you try to go to /index.html/ you will be redirected to /index.html/index.html, which will result in access denied, because CloudFront doesn’t map that URL.

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;
}