I have following nginx config:
server {
server_name dev.example.com;
root /home/example/develop/frontend/build;
location / {
rewrite ^/#(.*)$ $1 last; # for some reason this is not working
try_files $uri $uri/ /index.html;
}
location ~ .(static)/(js|css|media)/(. )$ {
try_files $uri $uri/ /$1/$2/$3;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/dev.example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/dev.example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
I've changed from React HashRouter to BrowserRouter, so I had to add those 2 location entries. Some of the links outside application are already generated, so I would like to redirect all hash urls to standard browser urls to make my app backward compatible, e.g.:
https://dev.example.com/#/somepage/123123
should be changed (or should redirect) to:
https://dev.example.com/somepage/123123
For some reason, none of the rewrite
rules I have written seems to work.
CodePudding user response:
As @RichardSmith mention in comment, everything after #
is processed by a browser, so it is never sent to the NGINX.
I've managed to solve this issue on the app client side.
My app routing looks like this:
<BrowserRouter>
<UserContextProvider>
<React.Suspense fallback={ loading }>
<Switch>
{/* routes */ }
</Switch>
</React.Suspense>
</UserContextProvider>
</BrowserRouter>
Solution:
In UserContextProvider
I've placed following code:
useEffect(() => {
if (location.hash.startsWith('#/')) { // checking if it's HashRoute
history.replace({
pathname: location.hash.replace(/#\/(.*)/, '$1'), // skipping `#/`
})
}
}, [])
After this change all the #
routes are "translated" into BrowserRoutes
and it works as expected, what means that my app is backward compatible with previously used HashRouter
.