Hosting multiple React apps from S3 via Cloudfront


We are hosting a react app in an s3 bucket via cloudfront, hosting on (s3 origin) and the backend via ELB on (elb orgin), with the default path going to the elb origin. We had to override the 403 response to get it to work, returning a 200 status with /app/index.html. We are unclear if there is any other workaround besides the custom error response, but if we want to add another app, say (another s3 orgin), we cannot because of the 403 custom error going to /app/index.html

Is there any way to get it to work without the custom 403 override or to have multipe 403 pages, one for each origin?

3 Answers

In order to run multiple apps under the same domain, you'll need to use Lambda@Edge or Cloudfront Functions to implement the functionality you need.

There are two options I can think of - either you examine the request and rewrite the URI path to /app/index.html, or you examine the response where you'd look for error codes and adjust the status code and body accordingly (see example here)

I think the response option is slightly more complex as you'd either need to embed the contents of index.html inside the function, or make a network call from the function to retrieve it from S3.

For the request option, I don't think we have any sample CloudFront functions that do exactly this, but there is one here that is close - just adjust the IF statements to suit- eg.

    if (uri.startsWith('/app1/')) {
        request.uri = '/app1/index.html';
    else if (uri.startsWith('/app2/')) {
        request.uri = '/app2/index.html';
answered 10 months ago
  • Of course I tried the hard way because that's what I started with, but you were right, origin request was the best and easier solution

Accepted Answer

Thanks to Paul L... Here is the python solution and a few notes about using python..

  1. You can't use a template, you have to create the lambda manually (make sure you don't select arm, only works with x86)
  2. Add a trigger for your cloudfront, for me I added it to my /app/* behavior and once I got that working I added to my /app2/* behavior, etc. You need to deploy to both to get them on the same verison.
# -*- coding: utf-8 -*-
import json
from os.path import splitext

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']

    #print("Request before ", request)
    ext = splitext(request['uri'])[1]
    #print("extension = ", ext)

    #only do this for URI's with no extension!!!
    if (ext == ""):
        if request['uri'].startswith('/app'):
            request['uri'] = '/app/index.html'
        elif request['uri'].startswith('/app2'):
            request['uri'] = '/app2/index.html'
        #print("Request after ", request)
    return request
answered 10 months ago

Hi, have you tested the Path Pattern option [1] ? That will give you a way to use specific origins for specif routes or paths.


profile picture
answered 10 months ago
  • not sure how that would help. According to every article we've found, you need to override 403 response to return 200 and the react apps index page. Path pattern seems to be just a way to control caching. How can I use it to solve this problem?

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions