Visiting Any URI other than Root Resulting in 404 - nginx - reactjs

I have a URL in the form of www.example.com, and am using nginx as the web server. When I go to www.example.com, the site works fine, however whenever I go to www.example.com/anyUri, I receive a 404. Here is the location element in my sites-available file:
location ~*/(.*) {
try_files $uri $uri/ = $404 ;
}
The website is built in React, so there is no real directory, but rather different routes. When I click on a link to navigate to a different route, it loads correctly, but if I try to access that same route directly through the URL, I receive the 404 as well. For example, if from my home page I click "Contact", the URL changes to www.example.com/contact and loads the "Contact" component as desired. If I refresh the page or type in www.example.com/contact manually, I receive the 404. I have my website set up to handle the nonexistent URIs accordingly, and do not need nginx to handle those. Instead, I want nginx to go to www.example.com/anyUri and let the website logic take over from there. I have tried looking up the different patterns online, however none seem to be working as desired.

This nginx.conf file is what I have been using - works like a charm for me.
server {
listen 80 default_server;
listen [::]:80 default_server;
root /your/web/root/path/nginx/html;
index index.html;
location / {
# Adds support for HTML5 history mode
try_files $uri $uri/ /index.html;
# -or-
# try_files $uri /index.html;
}
}

Related

NGINX configures front-end routing,404 cannot be returned

Ask a question, deploy React project with nginx, in order to configure the front-end routing of React Router, use $try_files for nginx to locate all routes into index.html, but there is a problem with this configuration,If you want to request other files, such as *.json, *.md, and if I request the json file in the directory, If the json file does not exist, the server will directly return the index.html file instead of returning 404. How to solve it?
location / {
alias /usr/local/var/www/;
index index.html;
try_files $uri index.html;
}
By default it looks like this:
try_files $uri $uri/ =404;
You don't need that index.html in try_files, since you have it as index option value.
The configuration file you have set for NGINX is always going to fall back to index.html, as it will attempt to match try_files in order. What you need to add is =404; or better yet, change:
try_files $uri index.html;
to the implementation found in user973254s answer. Otherwise, NGINX is always going to fall back to index.html.
Please see https://serverfault.com/questions/329592/how-does-try-files-work for a pretty detailed explanation. It directly addresses an instance where you append =404; to the try_files directive.
(Asked To Answer Via Queue)

Create react app served with nginx and oauth gives me refresh page issue

I have an app that is handled on server by https and it uses Oauth2 with tokens.
In react I have PathRouter which redirects to different pages
<Switch>
{/*the default is devices*/}
<Route exact path="/">
<Redirect to="/devices"/>
</Route>
and I have an nginx config
server {
listen 443 http2 ssl;
listen [::]:443 http2 ssl;
root /home/path-to-static;
index index.html;
server_name *****.com;
error_log /var/log/nginx/debug.log debug;
ssl_certificate /etc/nginx/certs/*****.crt;
ssl_certificate_key /etc/nginx/certs/*****.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
location / {
try_files $uri $uri/ #backend;
}
location #backend {
proxy_pass http://localhost:8080;
}
}
And it works!
The trouble starts when I want to refresh the page. Locally (on localhost) it works just fine, but when I refresh page on the server it won't let me and tells me that I am unauthorized.
I have a login screen where I enter my credentials and receive tokens and every request to the server I make with those tokens BUT my routing (I assume that) is the cornerstone that leads to the error- the inner routing happens without tokens.
Once again: it works fine until I refresh the page. Locally it works fine always.
That is the error that is provided on server
PS Maybe this is important: when I logined via login page and then I proceed to devices there is no devices request - as when I refresh the page via F5.
PS 2 I found a config when I am on some tab in my app and I clear all the uri but root and hit enter and it leads me to https://myapp.com/devices ! And it does it correct.
Ok, after reading tons of answers on SO I finally got it to work.
Firstly, a great answer from user #Panther here react.js application showing 404 not found in nginx server
When your react.js app loads, the routes are handled on the frontend
by the react-router. Say for example you are at http://a.com. Then on
the page you navigate to http://a.com/b. This route change is handled
in the browser itself. Now when you refresh or open the url
http://a.com/b in the a new tab, the request goes to your nginx where
the particular route does not exist and hence you get 404.
To avoid this, you need to load the root file(usually index.html) for
all non matching routes so that nginx sends the file and the route is
then handled by your react app on the browser.
So, as he recommended I've changed my config like
location / {
try_files $uri $uri/ /index.html #backend;
}
location #backend {
proxy_pass http://localhost:8080;
}
But this gave me some weird errors.
So I have to write location for every path I have, like this:
location / {
try_files $uri $uri/ #backend;
}
location /devices { // here my path is similar as in react
// router
try_files $uri $uri/ /index.html;
}

Nginx and multiple React Web Apps

I want to do some A/B testing in a React Web App and decided to duplicate it.
So I'm tring to set one app in the root location (example.com) and the other into a sub-folder (example.com/bversion).
For this, I'm using nginx for serve both versions.
server {
listen 80;
server_name example.com;
root /var/www/html/a_version;
location / {
try_files $uri /index.html;
}
location /bversion {
root /var/www/html/b_version;
try_files $uri /index.html;
}
}
The problem is that Ngnix never resolve /bversion. Always return the root A version of my app.
If I remove try_files in both locations, I lose the possibility to access directly to some specific pages of the application (e.g. example.com/hello or example.com/bversion/hello)

react always redirect to homepage

First of all I'm new to react, so i'm still learning about it.
I got this problem with react if I make a hyperlink from another domain/site to react app on localhost, eg http://localhost:8089/foo/bar. it show the correct page directly but if I make a hyperlink from another domain/site to a public domain with https protocol eg https://example.com/foo/baz it always redirected to homepage page (https://example.com/)
is there anything I can do to make it go straight to https://example.com/foo/baz. I run react on nginx web server with this redirection setting it went well for php, django etc but won't run with react.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com;
return 301 https://$server_name$request_uri;
root /home/[path to dist folder]/web/app/dist;
index index.html index.htm;
}
FYI the react app is build with webpack thanks in advance
I things the probleme is :
"return 301 https://$server_name$request_uri;"
You should maybe replace it :
"return 301 https://$server_name/$request_uri;"
I've manage to put the right config for the file.
it should be like this
server {
...
location / {
...
try_files $uri $uri/ /index.html;
}
...
}
thanks all for your help

How to configure Nginx to work with html5mode

For clean urls in angularjs I must use $locationProvider.html5Mode(true); but when I refresh my page it shows a 404.
I've read that I need to configure server file.
Structure
/html -
/views -
home.html
about.html
contact.html
index.html
app.js
What I've done so far:
nginx.conf
server {
root /html/views;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
The Angular HTML5 location mode basically took advantage of HTML5 history API to "simulate" URL changes in client. But the URLs are probably not real (not exist) from the point of view from server therefore it's not possible to locate those pages on the server. There are generally two solutions can let server to know the URLs:
Use server-side rendering. This is widely used by another framework called ReactJS. And actually AngularJS 2.0 can work on a server too. Therefore it is possible to generate the real pages server-side and serve them to the client.
Use HTTP server rewrite techniques. This is what you are trying to do. The idea is to forward all related requests to a single AngularJS entrypoint HTML page, normally it's the index.html from the root.
For your case, assume the entrypoint of AngularJS is /index.html. Try this:
server {
root /html/views;
index index.html;
location / {
try_files $uri $uri/ /index.html =404;
}
}
The previous solution is not perfect, because it will test every request arbitrarily. We can avoid unnecessary URL looking up by specify more detailed rules:
server {
root /html/views;
index index.html;
rewrite "^/users" /index.html last;
rewrite "^/pages" /index.html last;
...
}
Use regular expressions to match the URLs you want to serve with Angular.

Resources