Redirect to index.html for S3 subfolder

前端 未结 6 722
庸人自扰
庸人自扰 2020-12-25 12:37

I have a domain example.com. I have a S3 bucket named example.com setup with an index.html file that works. Now I like to create two s

相关标签:
6条回答
  • 2020-12-25 12:45

    You can try setting Redirection rules, Here is an untested rule.

    <RoutingRules>
      <RoutingRule>
        <Condition>
          <KeyPrefixEquals>old</KeyPrefixEquals>
        </Condition>
        <Redirect>
          <ReplaceKeyWith>old/index.html</ReplaceKeyWith>
        </Redirect>
      </RoutingRule>
      <RoutingRule>
        <Condition>
          <KeyPrefixEquals>new</KeyPrefixEquals>
        </Condition>
        <Redirect>
          <ReplaceKeyWith>new/index.html</ReplaceKeyWith>
        </Redirect>
      </RoutingRule>
    </RoutingRules>
    
    0 讨论(0)
  • 2020-12-25 12:47

    No need for a lambda function adding expense and complexity to your project.

    The following answer is quoted from https://stevepapa.com/

    https://stevepapa.com/my-great-new-post/ would be expected to work the same way as: https://stevepapa.com/my-great-new-post/index.html

    There’s a clever little way to get these flowing through to the Cloudfront distribution, and it involves changing the source origin from the one that Cloudfront presents to you by default.

    When selecting the origin source Cloudfront will show you a list of S3 buckets.

    Instead of setting the source from the bucket shown in the dropdown list, you’ll need to grab the static web hosting endpoint for that resource from its S3 settings page and pop it in manually.

    Using the static source for the Cloudfront distribution origin means any request to that distribution will be using the S3’s root object lookup, and your 404 responses should disappear as the references flow through.

    Important: After doing this, clear your browser cache and devalidate the items in your cloudfront distribution. Otherwise, the changes you made won't go live immediately.

    0 讨论(0)
  • 2020-12-25 12:54

    If you are using CDK to create a CloudFrontWebDistribution with an S3 source, then your first guess is probably to do this:

                    OriginConfigs = new[] {
                        new SourceConfiguration {
                            S3OriginSource = new S3OriginConfig
                            {
                                S3BucketSource = bucket
                            }
                            Behaviors = new[] { new Behavior { IsDefaultBehavior = true } }
                        }
                    }
    

    However, to configure cloudfront to use the website-bucket-url (that does have the behavior to resolve a directory to index.html), you need to use:

                    OriginConfigs = new[] {
                        new SourceConfiguration {
                            CustomOriginSource = new CustomOriginConfig
                            {
                                DomainName = bucket.BucketWebsiteDomainName,
                                OriginProtocolPolicy = OriginProtocolPolicy.HTTP_ONLY
                            },
                            Behaviors = new[] { new Behavior { IsDefaultBehavior = true } }
                        }
                    }
    

    You need to specify the protocol as HTTP_ONLY because website buckets do not support HTTPS. The default for a CustomOriginSource is HTTPS_ONLY.

    0 讨论(0)
  • 2020-12-25 12:58

    So I had this problem last night too.

    The issue is as follows: S3 when configured as a website bucket is forgiving and has the index document setting, set to index.html and this gets applied at the root, ie, example.com actually gets redirected to example.com/index.html, and it also gets applied at the subfolder level, so example.com/new or example.com/new/ should both redirect to example.com/new/index.html, where there would be an object in the bucket. (If not, you'd get a NoSuchKey error instead.)

    However you then "upgrade" yourself to CloudFront, likely for HTTPS, and this feature goes away. CloudFront instead makes explicit API calls to S3 and therefore doesn't trigger the index document concession. It does work for the root, but not for subfolders.

    The RoutingRules solution doesn't look clean to me because by specifying KeyPrefixEquals rather than key exactly equals (which doesn't exist) I think you'd get unintended matches.

    I instead have implemented a Lambda@Edge rule that rewrites the request that CloudFront makes to S3 to have a proper key value in it.

    Start with the Lambda docs and the A/B testing example here: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-examples.html#lambda-examples-general-examples

    Change the code to:

    'use strict';
    
    exports.handler = (event, context, callback) => {
        /*
         * Expand S3 request to have index.html if it ends in /
         */
        const request = event.Records[0].cf.request;
        if ((request.uri !== "/") /* Not the root object, which redirects properly */
            && (request.uri.endsWith("/") /* Folder with slash */
                || (request.uri.lastIndexOf(".") < request.uri.lastIndexOf("/")) /* Most likely a folder, it has no extension (heuristic) */
                )) {
            if (request.uri.endsWith("/"))
                request.uri = request.uri.concat("index.html");
            else
                request.uri = request.uri.concat("/index.html");
        }
        callback(null, request);
    };
    

    And publish it to your CloudFront distribution.

    0 讨论(0)
  • 2020-12-25 13:04
    1. Configure your Bucket to deliver a static website
    2. Create a CloudFront Distribution: set your bucket as the Origin and leave the OriginPath empty (default: /)
    3. Create Route53 RecordSet which links to your CloudFront Distribution

    You can find a helpful walkthrough here

    Question: What should happen if your customer enters example.com (without old/new)?

    Edit: 2. is optional. You could also link your Route53 RecordSet to your static website but CloudFront enables you to serve your wesbite with https (with help of AWS Certificate Manager).

    0 讨论(0)
  • 2020-12-25 13:11

    There is even easier way to accomplish this with an HTML redirect file

    1. Create a plain file named my-great-new-post (don't worry there won't be a name conflict with the folder in the same bucket)

    2. Write a meta-redirect code in that file (I pasted the code below)

    3. upload file to root bucket (where my-great-new-post folder lays)

    4. modify metadata of the new file and make Content-Type:text/html

    Here lays the content of the file:

    <!DOCTYPE html>
        <html>
        <head>
        <meta http-equiv="refresh" content="0; url=/my-great-new-post/index.html">
        </head>
        <body>
        </body>
        </html>

    0 讨论(0)
提交回复
热议问题