2

I'm using S3 routing rules to deprecate an old domain, routing the traffic to a new domain. So, the old domain was product.com, and the new location is my-organization.com/product/.

I am using routing rules to redirect pages. So, I have a rule like this that redirects the FAQ:

    <Condition>
        <KeyPrefixEquals>faq</KeyPrefixEquals>
    </Condition>
    <Redirect>
        <Protocol>https</Protocol>
        <HostName>my-organization.com</HostName>
        <ReplaceKeyPrefixWith>product/faq</ReplaceKeyPrefixWith>
        <HttpRedirectCode>301</HttpRedirectCode>
    </Redirect>

This works well!

The one thing left to do is redirect the old homepage to the product page. I've tried using / to match the homepage:

<KeyPrefixEquals>/</KeyPrefixEquals>

But it doesn't seem to match anything. And I've tried matching on the empty key:

<KeyPrefixEquals></KeyPrefixEquals>

But that matches everything. Is there a way to just redirect the homepage in S3 routing rules? What I want is something like:

    <Condition>
        <KeyPrefixEquals>/</KeyPrefixEquals>
    </Condition>
    <Redirect>
        <Protocol>https</Protocol>
        <HostName>my-organization.com</HostName>
        <ReplaceKeyPrefixWith>product/</ReplaceKeyPrefixWith>
        <HttpRedirectCode>301</HttpRedirectCode>
    </Redirect>

Thanks!

1 Answer 1

2

The root of a bucket isn't /, it's empty string. An empty key prefix wouldn't do exactly what you want, since everything has a prefix that matches an empty string (because LEFT(${some_string},LENGTH('')) == '', regardless of the content of ${some_string}), so such a rule wouldn't match only the root, in any event. It would match everything.

There is no way to specifically redirect the root page only, but here's the workaround that I've been using that works well. Place this as your last routing rule (since they're matched in order, and this one does indeed match everything that hasn't already been matched, if there's not already a page there).

<RoutingRule>
    <Condition>
        <HttpErrorCodeReturnedEquals>403</HttpErrorCodeReturnedEquals>
    </Condition>
    <Redirect>
        <ReplaceKeyPrefixWith>product/</ReplaceKeyPrefixWith>
        <Protocol>https</Protocol>
        <HostName>new-site.example.com</HostName>
    </Redirect>
</RoutingRule>

You should not have public listing of the bucket enabled, but if you do, you'll need to replace 403 with 404. If you have an index document, you'll need to remove it.

Essentially, for any request that would be denied due to the lack of a public page at that path, product/ gets appended so http://bucket.example.com/ becomes https://new-site.example.com/product/.

Similarly, http://bucket.example.com/some/random/file.txt will redirect to https://new-site.example.com/product/some/random/file.txt but the old page was already invalid, so the new page will be invalid, so nothing lost/nothing gained. Since rules are matched in order, this rule shouldn't break anything else if you add it last.

Or, depending on the grand scheme of what you're actually needing to do, this rule may actually be the only redirect rule you need, once you remove the old content from the bucket.

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

3 Comments

Shoot. This is where I annoyingly add more requirements that I forgot to mention. The other requirement is that I already have a catch-all rule, which redirects blog posts from the old domain to the new one. The blog posts simply map across so their old path is the same on the new domain. So, the root goes to the product page, feature pages (like the FAQ) get placed under the product page, and blog posts just map across (but can't be enumerated). I think the final solution is to just make the blog posts redirect to the product page. Lame, but it'll work.
Possible hackaround: add x-amz-website-redirect-location to the metadata of the object index.html (whatever you used as index document name) at the root of the bucket, with the value of https://new-site.example.com/product/. These are handled as 301, assuming S3 handles redirecting from an index document.
Object redirect on index.html does not work unless you actually type "index.html" into the URL.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.