Search code examples
amazon-web-servicesamazon-s3aws-api-gatewayapi-gateway

AWS: serve multiple sites under the same domain


I own a domain name my-portal.com. I want to serve a static website from my-portal.com/site/a/. I want to serve another static website from my-portal.com/site/b/.

How can I do that with resources that AWS provides?

I was trying to setup two websites as two separate S3 buckets with static website hosting enabled and then created an API Gateway with resources /site/a and /site/b configured as HTTP proxy to S3 websites.

This setup worked correctly for most of the cases. But when a browser tries to load a binary file (font, image, etc.) from my static website, the API Gateway does not properly handle that file and responds with the corrupted one (because it behaves strangely with binary files).

What other ways to achieve the same result do I have?


Solution

  • Solution #1: Use CloudFront + Lambda@Edge

    CloudFront allows to configure multiple cache behaviors, routing different path patterns to a respective origins:

    • https://my-portal.com/site/a => https://bucket-a.s3-website.amazonaws.com/site/a
    • https://my-portal.com/site/b => https://bucket-b.s3-website.amazonaws.com/site/b

    The only limitation is that each S3 bucket should be aware of the path and provide the same file structure within it. The bucket for the website A should contain the folder /site/a, the B bucket should contain the folder /site/b.

    It's possible to overcome this limitation by using Lambda@Edge.

    Solution #2: Configure Binary File Mimetypes in API Gateway

    API Gateway allows to configure binary file mime types. But it requires requests to have the Accept header compatible with the mime types configured.

    So, for example, if you configure a image/* as a binary mimetype in APIG, your requests for images should have Accept header with the value of image/png, image/jpg or just image/*. If the header is missing or it has some other value, APIG won't treat the response as a binary file.

    The problem here is that browsers usually send Accept: */* when they try to load resources imported from CSS.

    So, the only solution to this would be to configure */* as a binary mimetype. This will break all non-binary responses served by this API Gateway, like JSON ones.

    Solution #3: Host binary files separately

    This is a combination of the previous two approaches. You can just create a separate static website hosting and put your binary files there.