Redirect to index.html for S3 subfolder

前端 未结 6 741
庸人自扰
庸人自扰 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: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.

提交回复
热议问题