I'm running an nginx SPA application.However for requests I would like a fallback/fallthrough approach:
I have the main directory /
which has the main /index.html
as well as "default" icons. However it also contains a subdirectory /local/
which contains (potentially) values from the default directory - overwriting those existing ones. (This is to allow a docker volume, to provide specific favicon.ico etc from the host OS and modify that without rebuilding the docker).
Initially I had the following proxy directive:
root /var/www/html;
location / {
# redirect everything to show the main SPA application
try_files $uri $uri/ /index.html;
expires 7d;
}
location = /index.html { }
Which works, however it does not prefer the files under /local
unless specified in the request.
I then tried to add a longer try_files list:
root /var/www/html;
location / {
# redirect everything to show the main SPA application
try_files $uri/local $uri/local/ $uri $uri/ /index.html;
expires 7d;
}
location = /index.html { }
However now if I go to the mainpage localhost:80
a redirect (301) to localhost//local/
happens
I feel I do not understand the try_files function. And secondly I wonder how above can be done. In summary this is the lookup I wish nginx to do (notice no redirection for frontend):
localhost/ => ./index.html
localhost/favicon.ico => ./local/favicon.ico //IF that file exists
localhost/favicon.ico => ./favicon.ico //IF ./local/favicon does not exist
localhost/unexistingfile => ./index.html
How would I do this? Or is this impossible at nginx level and should I do this in the application layer?
Considering the request //localhost/favicon.ico
, the value of $uri
is set to /favicon.ico
.
The file term $uri/local
will cause Nginx to search for a file at /var/www/html/favicon.ico/local
, which is not your intent.
The correct file term is /local$uri
, which will cause Nginx to search for a file at /var/www/html/local/favicon.ico
.
From the try_files
documentation:
It is possible to check directory’s existence by specifying a slash at the end of a name
When Nginx finds a directory using try_files
in this way, it issues an external redirection to a URL with a trailing /
. URLs with a trailing /
that resolve to a directory are then processed by the index module.
Your file term $uri/local/
is matching the directory /var/www/html/local
for the //localhost
request, which causes the unwanted redirection to //localhost/local/
.
In summary, use:
try_files /local$uri $uri $uri/ /index.html;
First, the file term /local$uri
will look for files under the local
subdirectory.
Second, the file term $uri
will look for files starting from the root.
Third, the file term $uri/
will perform normal index processing where the URL resolves to a directory.
The final parameter is a URI, which causes Nginx to generate an internal redirection to index.html
if none of the file terms found a match.