I just launched my first working Back4App application. This application is a React app with the React Router. To make it work, I did a npm run build
and uploaded all the files under the 'public' folder (found at Cloud Code).
Now everything is in place, I can go to the index page, that is https://[myapp].b4a.app, and everything works well. But when I go to a subpage and do a refresh, I stumble upon a 403 - {"error":"unauthorized"}
error.
I do understand this happens because the user tries to go where my app is not served. Normally I would put Nginx or something similar in the middle; so I could catch those requests and redirect them to the SPA.
But now, as I don't have control on the backend side at all, how can I make this work?
Back4App uses Express, a Node.js web application framework, as a backend. Luckily for us, we can add a routing file ourselves. Just go to your Cloud Code section and add an app.js
file in the cloud folder:
The Routing & Single Page Application FAQ states:
To configure the routing to your SPA in Express, you should use the GET HTTP method to include an HTML file and in the response, we are going to deliver the index.html file to the browser.
It means you have the route all possible GET request to your index.html, except of the Back4App reserved paths (like 'login' and 'logout' for instance). A working basic file can also be found from the documentation:
const path = require('path');
const unRoutedPaths = ['apps','batch','requestPasswordReset','files','login','logout','user','users','Roles','parse','schemas','functions','classes','aggregate','cloud_code','config','hooks','push_audiences','installations','push','sessions','events','jobs','export_progress','export_data','graphql','import_data'];
app.use((req, res, next) => {
const pathParts = req.path.split('/').filter((p) => p !== '');
if (req.path.indexOf('.') > 0 || unRoutedPaths.includes(pathParts[0])) {
next();
} else {
res.sendFile(path.join(`${__dirname}/public/index.html`));
}
});