0

I have a static Gatsby website hosted on S3 + Cloudfront. The site is working fine with custom error responses with path set to /index.html for error code 403

But when I try to manually enter a specific page path exmaple.com/path1 in the browser tab and hit enter, it redirects me to the home example.com page.

Why is that? Is there any solution for this?

My s3 permission policy:

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::example.com/*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::111111111111:distribution/f6666666"
                }
            }
        }
    ]
}

1 Answer 1

1

I don't know much about Gatsby but I'm guessing that it's generated a structure like this which you've deployed to your S3 bucket?

/index.html
/path1/index.html
...etc

And you want GET / to return the content from index.html, and GET /path1 to return the content from /path1/index.html etc.? And your plan to do this was to set /index.html as the 403 custom error response?

If I've understood that correctly, then this isn't going to work as you want. If you've set things up as described I would expect GET /path1 to return the content from /index.html.

One way of getting this working as you want is to change the 403 custom error response to something more appropriate (i.e. a /404.html page) and then associate a viewer-request function with your CloudFront distribution that rewrites requests to include /index.html at the end of the path if needed. Something like:

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

  if (uri.endsWith("/")) {
    request.uri += "index.html";
  } else if (!uri.includes(".")) {
    request.uri += "/index.html";
  }
  return request;
}

Here's a CloudFormation template where this is set up if you want to see how it all fits together (disclaimer: this is my github repo).

Sign up to request clarification or add additional context in comments.

6 Comments

Yes, that is the case. I understand. Right so this is one way. I found another way: to avoid cloudfront. and use direct s3 website hosting endpoint set as A record of custom domain on Route53. But this approach is running the site on http protocol despite custom domain issued with ACM SSL certificate. Can you explain why?
S3 website hosting doesn't support https. If you want to host S3 content over https then CloudFront is the way to go.
I just trying to avoid the cost of using cloudfront functions given high volume of traffic i receive. Also, I'm using SSL custom domain in front, so that should support https, then Is that right? Thank you for your responses
CloudFront functions are pretty cheap - like $0.10 per million invocations and I think you get the first couple of million free. And you should be able to reduce cost further with caching for a static site. But no, just because you have an SSL cert for your domain does not mean any service will support https. You need something to use the cert to terminate SSL traffic. CloudFront does that, S3 web hosting doesn't.
if you don't like CF functions another option would be to reorg the file structure in S3 - e.g. when uploading rename /path1/index.html to /path1 and make sure it has the correct meta data set
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.