-
Notifications
You must be signed in to change notification settings - Fork 106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Static Website] Getting 404 on nested paths, and security headers are not applied #172
Comments
Thanks a lot for all these details! Lambda@Edge is unfortunately very invasive and unpractical, at least from my original experience (creates Lambda functions in many regions, logs in many different regions). For hosting a static website I'd love to avoid that if possible. Do you think there is any other option than using Lambda@Edge? |
If we want to keep the S3 set up with website hosting, thus leaving the configuration of error behaviors on its side, I'm afraid we cannot 😕 . A solution that does not require Lambda@Edge would be to revert #165, manually generate the OAI to allow I am not 100% sure of this, I'm guessing that it is the problem that @CorentinDoue is facing. |
Yes, if cloudfront gets an error from S3 (a 404 for example), the CloudFront functions are not triggered. Even if this error is explicitly handled (returning a 200 and index.html for example). With |
We also found another possible solution that doesn't require Lambda@Edge on StackOverflow: https://stackoverflow.com/a/69479703/11788663 It adds a viewer request CloudFront function to transform the request from @adriencaccia suggest we split the static-website construct into static-website and spa-website construct because spa requires special treatments |
Indeed, we can see that to make SPA work we will require special configurations. What do you think of adding a SPA construct with the solution specified in @CorentinDoue comment ? ie: using a viewer request cloudfront function to rewrite the URI to |
Yeah, the more we progress on this construct the more it seems like a separating SPA from purely static websites makes sense. This is a big change though (which I personally still prefer over Lambda@Edge), @fredericbarthelet is that OK with you? |
Thanks @adriencaccia for opening this issue and @CorentinDoue for the additional insights. Amplify provides 2 hosting strategies:
The later one, which is closer to our current solution does not implement any lambda@edge. It is not possible to add custom headers as port of Cloudfront response. The first one however supports the requested feature described above. You can:
The SPA redirect strategy uses a dedicated regex pattern to ensure only SPA paths are redirected to What I suggest:
@adriencaccia @CorentinDoue @mnapoli, WDYT ? |
It seems to me that using the regex for redirects in static website (not SPAs) is risky. You can see that the regex of amplify does redirect I think your recommendation to have 2 constructs is great.
A small correction, it will be a cloudfront function and not a lambda@edge If we all agree, I'd be happy to implement it 🙂 |
Description
When trying to directly access a nested path of a SPA deployed with the static website construct, we get a 404 response and the security headers are not applied.
Although a 404 is received, the content is the page is still the desired one.
Regarding the 404:
When building a SPA with a modern framework, we want to leave the handling of "bad routes" to the application itself. Since we cannot know in advance which routes are served by the application, I think a better approach would be to always return a 200 on nested routes.
Why we get the 404
The construct is deploying a Cloudfront with a S3 with website hosting as an origin. The default behavior of a S3 with website hosting when trying to request a non-existing file is to return a 404 and display the error document if it is set.
For SPAs, we want this error document to be the same as the root document of our app. Lift is configured to work like this by default.
So, when hitting a nested route, Cloudfront receives a 404 from S3 and then return it to the client.
Why the security headers are not applied
The security headers are applied thanks to a Cloudfront function deployed by Lift, which is set up to be invoked by viewer response events.
Per the Restrictions on edge functions docs, CloudFront does not invoke edge functions for viewer response events when the origin returns HTTP status code 400 or higher.
Thus when trying to get a nested route, Cloudfront will not apply the function because S3 (the origin) is returning a 404.
Proposed solution
Adding a Lambda@Edge triggered by the origin response trigger to rewrite 4xx to 200 will solve the problem.
This is a common use case for Lambda@Edge, per the docs.
I will submit a PR following this issue to implement it !
Kudos to @CorentinDoue and @guillaumem-theodo for finding this bug !
How to Reproduce
A created a single file SPA with react and nested routes to showcase the problem.
Accessing the deployed cloudfront domain with the nested routes
/login
or/register
will result in the bug described above.Lift config in
serverless.yml
:build/index.html
Additional Information
Versions of npm packages:
The text was updated successfully, but these errors were encountered: