Search code examples
amazon-web-servicesamazon-s3amazon-elastic-beanstalkamazon-cloudfrontamazon-route53

How to replace %23 with # before loading website?


I have a Flutter web app that makes use of the # (SPA). An external source has the URL for this app, but with %23 instead of #, and I have no control there to change this behavior, so I need to fix this on my side.

Since it's a static web app, I hosted on S3 static hosting (AWS), then configured a redirect like this:

[
    {
        "Condition": {
            "KeyPrefixEquals": "%23/"
        },
        "Redirect": {
            "ReplaceKeyPrefixWith": "#/"
        }
    }
]

I also tried ReplaceKeyWith instead of ReplaceKeyPrefixWith, not sure what's the difference. This approach worked as I remember.

After that I needed to hook it to a CloudFront distribution for caching purposes, but as soon as I did that, the redirect stopped working. While on the distribution URL with %23, it will redirect to S3 URL instead of CloudFront's. I thought that this meant I needed to move the redirect on CloudFront level.

And I tried to do that. But the problem was I didn't find a simple solution just like S3 redirect way. For CloudFront I must deploy a lambda@edge function at Viewer Request to decode the URL if necessary. This approach though introduces overhead, possible cold start and scaling issues. All of these issues just to fix a simple %23 character in the URL.

I thought of switching to Elastic Beanstalk, but this means I need to configure a simple Node.js server file to host the html directory. That's doable, and rewriting the URL should be doable as well from Nginx config files. But how can I hook this beanstalk to CloudFront? A single server won't work, since it requires a load balancer as I understand. So having two server instances for a simple html website is an overkill.

Now that you have all of this context, what do you suggest? How can I fix the %23 issue while keep using S3 for hosting?

S3 makes the most sense.


Solution

  • I ended up configuring a load-balanced beanstalk app with min and max instances set to 1. After that I was able to use this in cloudfront, and then with route 53. Everything works as expected now.