Search code examples
amazon-web-servicesamazon-s3amazon-cloudfront

AWS CloudFront misinterprets routing rule and redirects resource back to S3 bucket object URL


I have an AWS S3 bucket; let's call it example.com. I have the bucket configured for static web site hosting; the bucket static site URL for example might be http://example.com.s3-website-us-west-1.amazonaws.com. I also have a CloudFront distribution with an AWS-managed certificate, so that when I access https://example.com/ for example it serves content out of the S3 bucket http://example.com.s3-website-us-west-1.amazonaws.com/. That all works like a dream.

On my site I have a file https://example.com/foo.html that has been renamed to https://example.com/bar.html. Some other pages on the web may link to foo.html, so in my S3 bucket configuration I set up a redirect for the foo.html object, like this:

<RoutingRules>
  <RoutingRule>
    <Condition>
      <KeyPrefixEquals>foo.html</KeyPrefixEquals>
    </Condition>
    <Redirect>
      <ReplaceKeyWith>bar.html</ReplaceKeyWith>
    </Redirect>
  </RoutingRule>
</RoutingRules>

When I try to browse to http://example.com.s3-website-us-west-1.amazonaws.com/foo.html, it sends an HTTP 301 permanent redirect to bar.html, so I wind up at http://example.com.s3-website-us-west-1.amazonaws.com/bar.html, just like I expect.

So now I deploy the S3 bucket to a CloudFront distribution as explained above. After the CloudFront status shows "Deployed", I browse to https://example.com/foo.html, expecting to be redirected to https://example.com/bar.html. Oh, no; I am directed to http://example.com.s3-website-us-west-1.amazonaws.com/foo.html insetad!

Why is the CloudFront distribution redirecting me back to the literal S3 bucket URL? Why doesn't the object redirect to a relative object in the same bucket being correctly deployed to CloudFront?

Note that I am aware of the other question AWS Cloudfront redirecting to S3 bucket, but that does not appear to be a duplicate question of this one, as the other question is referring to the entire CloudFront site temporarily redirecting to the entire S3 bucket, not the failure of an individual S3 object redirect to be deployed to CloudFront.


Solution

  • First of all, CloudFront doesn't follow redirection from origin and it received the response from S3 and it served it to the client as it is. S3 is sending this response because in S3 redirect rules, you also need to specify the HOST value.

    e.g:

    <HostName>...</HostName>
    

    You can define hostname as the name example.com ot https://example.com, The hostname to be used in the Location header that is returned in the response.

    https://docs.aws.amazon.com/AmazonS3/latest/dev/how-to-page-redirect.html

    Note: Remember to clear the cache before you make changes and test again, cloudfront also caches 3xx response.