Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove root / from S3 cloudfront static website redirect

I have a static S3 website that just points to a different domain: https://www.externaldomain.com/id12345

This S3 is assigned to a CloudFront which is then assigned to A record to mydomain.com

The result is that when I navigate to mydomain.com it redirects visitors to https://www.externaldomain.com/id12345

Everything works fine, except it redirects to https://www.externaldomain.com/id12345/ with the / at the end

How can I make it redirect to exactly https://www.externaldomain.com/id12345 without the /

I do not have control over the externaldomain.com and it gives 404 when / is included.

like image 821
OutFall Avatar asked Jan 25 '26 10:01

OutFall


1 Answers

When you select the option to redirect all requests to another host, S3 assumes you want to preserve the original request path at the end of the new URL. Request URIs always begin with /, so when S3 appends the incoming request URI onto the path you provided when generating the redirect, there's the / from your request at the end. It's not so much that S3 is adding it, as that it is copying it from the incoming request URI.

So the behavior is confusing at first glance, but not incorrect.

What you stated in comments that you want to do is, regardless of the path, throw it away. All requests go to a single path on the destination service.

For this, use a routing rule. Select "Use this bucket to host a web site" and then make up a name for an Index Document -- you don't actually need one for this use-case, but the field is not optional, so just enter index.html. Then, add a redirection rule that looks like this:

<RoutingRules>
  <RoutingRule>
    <Condition>
        <KeyPrefixEquals></KeyPrefixEquals> <!-- empty string matches all requests -->
     </Condition>
    <Redirect>
        <Protocol>https</Protocol>
        <HostName>other-site.example.com</HostName>
        <ReplaceKeyWith>12345</ReplaceKeyWith> <!-- new path, with *no* leading slash -->
    </Redirect>
  </RoutingRule>
</RoutingRules>  

See Advanced Conditional Redirects in the S3 Developer Guide for more about the routing rule syntax.

The documentation doesn't mention using an empty <KeyPrefixEquals> to match all requests, but this works because what you're asking the rule to test is (pseudocode) left(key,0) == '', which of course is always true.

Also not explicit is the fact that S3 object keys, by convention, do not start with / (the leading / used in HTTP is, conceptually, before the first character of the object key). This is why <ReplaceKeyWith> and any other key reference doesn't need (and shouldn't have) a leading / in redirect routing rules.


Best practice suggests you ignore the following alternative solution, presented for your consideration. It is horrible, hacky, and wrong in so many ways, but it should work for many applications...

Use the "Redirect requests" option, as you originally were doing, but put # at the end of the path you provide. Then S3 redirects to https://example.com/12345#/ or, more precisely, https://example.com/12345#${original_uri}. Because # marks the beginning of the URI Fragment, it isn't sent to the destination server, so it should do what you want, too, though it may interact with an SPA router, if that's what you're using.

like image 173
Michael - sqlbot Avatar answered Jan 26 '26 23:01

Michael - sqlbot



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!