We are having issues trying to make working a SPA with a client router (react router). We are using the concept of have a DOMAIN -> CDN (CloudFront) -> S3
for serving our static files.
We have configured the S3 for serving static files. The CDN are configured to have the origin from the S3 and we have configured custom error pages to catch errors:
with this configuration we can catch errors like this:
https://www.example.com/custom-url
The CDN will redirect all the 404/403 errors to the main index.html
and react router
will get the correct routing.
We have working our site, and the client router is working fine, but we have a problem with the response of our CDN with x-cache: Error from cloudfront
:
If we access to the main url https://www.example.com
without any query param (not query string) all works fine.
How can I solved this problem and make that all my dynamic URLs work?
Thanks.
When you visit http://mywebsite.com
the request will hit the index.html
file in S3. Then you might click a button and go to http://mywebsite.com/stats
which is an internal route of your SPA app. Thus, it will not trigger any backend request.
But if you reload the page, http://mywebsite.com/stats
will be sent to S3 as your browser does not know that you are running an SPA frontend.
S3 will return 403 error with index.html and Cloudfront will send you the error.
Solution is using an edge lambda function in Cloudfront. Here an example:
const path = require('path')
exports.handler = (evt, ctx, cb) => {
const {request} = evt.Records[0].cf
if (!path.extname(request.uri)) {
request.uri = '/index.html'
}
cb(null, request)
}