'How to handle 403 and 404 errors with AWS Cloudfront containing multiple origins

I have the current configuration in AWS:

  1. S3 Bucket set to static website for my frontend

  2. ELB which has an EC2 instance for my backend

  3. Cloudfront distribution with two origins, two behaviors, and two custom error pages

    • Origins:
      • S3 Bucket (static website)
      • dev-api.mydomain.com (ALIAS record mentioned below that points to ELB)
    • Behaviors:
      • "/api/*" routes to dev-api.mydomain.com
      • "*" routes to S3
    • Error pages (this part is the most important to my question):
      • 403 returns 200 response with index.html (which comes from S3)
      • 404 returns 200 response with index.html (which comes from S3)
  4. Route53:

    • registered domain
    • dev.mydomain.com points to cloudfront distribution
    • dev-api.mydomain.com points to ELB

How do I distinguish between the 403 and 404 errors that come back from my S3 and backend server?

Note: I am using react router to handle all routing in the static website so every request to S3 would return a 404 from S3 unless the user specifically asked for the /index.html resource.

Scenario 1: When a user goes to dev.mydomain.com/logi (mispelled login), I would expect that to hit my S3 bucket and return with a 404 which would then fetch the index.html file in the bucket. Cloudfront would return the index.html file with a 200 OK Status and my application would handle the invalid route by displaying a 404 page.

Scenario 2: When a user goes to dev.mydomain.com/login, it would hit my S3 bucket, return with a 404 and return the index.html file. Once I land on the login page, for this examples sake, I fire off a network request to dev.mydomain.com/api/non_existant_route. I would expect that to hit my API server and return with a 404 which my frontend would then handle by displaying an error message about the API request failing.

However what is happening in Scenario 2 is that a 404 is returned from my backend server to Cloudfront, which then returns the index.html file (from S3) as the response with a 200 status code.

So, my question is - Is it possible to configure Cloudfront to return different error pages based on the origin that is sending back the error code? If not, how can I accomplish returning the correct response for the backend server?

Would it require me to re-architect my AWS solution?



Solution 1:[1]

Another way is to:

  • turn on Static Web Hosting on S3
  • replace the S3 bucket name in CloudFront origin with the S3 Static Website URL.
  • remove Error Pages from CloudFront.

The error pages will be handled by the respective origins instead of CloudFront.

Solution 2:[2]

I was able to solve the 403 and 404 issues by removing Custom Error responses from cloudfront.

I created a Lambda@Edge function on the default behavior (*) which routes to my S3 bucket. On Origin Request, the function modifies requests to pages like /login to instead return /index.html from the bucket.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Siraj Ahmad
Solution 2 pantaphobic