S3 Static Website Routing Redirects

AWS S3 static website hosting is a wonderful way to skip configuring apache and maintaining a web server. Like all technology choices it comes with some tradeoffs, for example, the inability to configure apache or nginx. You have to live with the limited tools provided by S3.

The Problem

When S3 receives a request it looks for a matching key. If you have an index.html and some assets, and your URL looks like:

http://website.com/route-a/route-b/route-c

The key will not exists. As a result, S3 will return a 404. If you configure the "error document" you can return the index.html file, but with a 404 status code. Google et al may not be into this.

One time tested solution for this problem is to use a *#!* in the path. In practice this is just fine, but what if you really don't like urls that look weird, and want your users to have non-#! URLs to use. Well, here's a janky solution that kind of works.

Solution Step 1: The redirect rule

<RoutingRules>
  <RoutingRule>
    <Condition>
      <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
    </Condition>
    <Redirect>
      <ReplaceKeyPrefixWith>#!/</ReplaceKeyPrefixWith>
      <HttpRedirectCode>301</HttpRedirectCode>
    </Redirect>
  </RoutingRule>
</RoutingRules>

This rule has a simple purpose. If the response from S3 was going to have a 404 status code (Condition Tag), then redirect with a 301 to the same URL but with a *#!*.

This allows us to get past the 404 response, a serve the SPA.

Solution Step 2: Changing the URL before anyone notices

if ((pathArray[3].indexOf("#!") >= 0)) {
  window.history.replaceState({}, '', location.href.replace("/#!/", "/"));
}

Put this into your SPA and change the URL by removing the #!. Preferably before anyone notices.

Final Thoughts

The cloud can be annoying. You no longer have the flexibility to just configure stuff the way you want. But you get to be server-less, and cool, and forget about a handful of monitoring and configuration management responsibilities.