How do you set a default root object for subdirectories for a statically hosted website on Cloudfront?

前端 未结 9 1929
[愿得一人]
[愿得一人] 2020-12-22 17:33

How do you set a default root object for subdirectories on a statically hosted website on Cloudfront? Specifically, I\'d like www.example.com/subdir/index.html

相关标签:
9条回答
  • 2020-12-22 18:11

    I know this is an old question, but I just struggled through this myself. Ultimately my goal was less to set a default file in a directory, and more to have the the end result of a file that was served without .html at the end of it

    I ended up removing .html from the filename and programatically/manually set the mime type to text/html. It is not the traditional way, but it does seem to work, and satisfies my requirements for the pretty urls without sacrificing the benefits of cloudformation. Setting the mime type is annoying, but a small price to pay for the benefits in my opinion

    0 讨论(0)
  • 2020-12-22 18:20

    UPDATE: It looks like I was incorrect! See JBaczuk's answer, which should be the accepted answer on this thread.

    Unfortunately, the answer to both your questions is no.

    1. Is it possible to specify a default root object for all subdirectories for a statically hosted website on Cloudfront?

    No. As stated in the AWS CloudFront docs...

    ... 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.

    ...

    The behavior of CloudFront default root objects is different from the behavior of Amazon S3 index documents. When you configure an Amazon S3 bucket as a website and specify the index document, Amazon S3 returns the index document even if a user requests a subdirectory in the bucket. (A copy of the index document must appear in every subdirectory.)

    2. Is it possible to setup an origin access identity for content served from Cloudfront where the origin is an S3 website endpoint and not an S3 bucket?

    Not directly. Your options for origins with CloudFront are S3 buckets or your own server.

    It's that second option that does open up some interesting possibilities, though. This probably defeats the purpose of what you're trying to do, but you could setup your own server whose sole job is to be a CloudFront origin server.

    When a request comes in for http://d111111abcdef8.cloudfront.net/install/, CloudFront will forward this request to your origin server, asking for /install. You can configure your origin server however you want, including to serve index.html in this case.

    Or you could write a little web app that just takes this call and gets it directly from S3 anyway.

    But I realize that setting up your own server and worrying about scaling it may defeat the purpose of what you're trying to do in the first place.

    0 讨论(0)
  • 2020-12-22 18:23

    There IS a way to do this. Instead of pointing it to your bucket by selecting it in the dropdown (www.example.com.s3.amazonaws.com), point it to the static domain of your bucket (eg. www.example.com.s3-website-us-west-2.amazonaws.com):

    Thanks to This AWS Forum thread

    0 讨论(0)
  • 2020-12-22 18:23

    There is one other way to get a default file served in a subdirectory, like example.com/subdir/. You can actually (programatically) store a file with the key subdir/ in the bucket. This file will not show up in the S3 management console, but it actually exists, and CloudFront will serve it.

    0 讨论(0)
  • 2020-12-22 18:26

    @johan-gorter indicated above that CloudFront serves file with keys ending by / After investigation, it appears that this option works, and that one can create this type of files in S3 programatically. Therefore, I wrote a small lambda that is triggered when a file is created on S3, with a suffix index.html or index.htm

    What it does is copying an object dir/subdir/index.html into an object dir/subdir/

    import json
    import boto3
    
    s3_client = boto3.client("s3")
    
    def lambda_handler(event, context):
    
        for f in event['Records']:
    
            bucket_name = f['s3']['bucket']['name']
            key_name = f['s3']['object']['key']
            source_object = {'Bucket': bucket_name, 'Key': key_name}
    
            file_key_name = False
    
            if key_name[-10:].lower() == "index.html" and key_name.lower() != "index.html":
                file_key_name = key_name[0:-10]
            elif key_name[-9:].lower() == "index.htm" and key_name.lower() != "index.htm":
                file_key_name = key_name[0:-9]
            
            if file_key_name:
                s3_client.copy_object(CopySource=source_object, Bucket=bucket_name, Key=file_key_name)
    
    0 讨论(0)
  • 2020-12-22 18:31

    Another alternative to using lambda@edge is to use CloudFront's error pages. Set up a Custom Error Response to send all 403's to a specific file. Then add javascript to that file to append index.html to urls that end in a /. Sample code:

    if ((window.location.href.endsWith("/") && !window.location.href.endsWith(".com/"))) {
        window.location.href = window.location.href + "index.html";
    }
    else {
        document.write("<Your 403 error message here>");
    }
    
    0 讨论(0)
提交回复
热议问题