I have a Django backend and Vue.js frontend served by the same machine. I want a specific path to be directed to the django API and admin panel, while the rest should load Vue index.html and be passed to Vue router. My problem is, that while the base path is passed on to Vue.js, and my selected path does go through to Django, any other path results in 404, which means that if I want to revisit a path generated though Vue router, it's impossible to do so.
I figured the problem must be somewhere in the NginX config file:
# the upstream component nginx needs to connect to
upstream myproject {
server unix:///tmp/myproject .sock;
}
server {
listen 80;
listen [::]:80;
server_name serverurl.com;
return 301 https://serverurl.com$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /home/projects/myproject/ssl/ANY.serverurl.com.crt;
ssl_certificate_key /home/projects/myproject/ssl/ANY.serverurl.com.key;
server_name serverurl.com www.serverurl.com;
access_log /home/projects/myproject/logs/nginx_access.log;
error_log /home/projects/myproject/logs/nginx_error.log;
location / {
root /home/projects/insights/vue/dist;
try_files $uri $uri/ /home/projects/myproject/vue/dist/index.html =404;
}
location /backend/ {
include /etc/nginx/uwsgi_params;
uwsgi_pass myproject;
}
location /static/ {
alias /home/projects/myproject/static/;
}
location /media/ {
alias /home/projects/myproject/media/;
}
}
So the "/" path results in correctly rendering Vue index.html
And "/backend/" correctly loads django urls
But, for example, if the user tries to access "/" and is not logged in, he will be redirected to "/login" by Vue router, which works fine and the login page works correctly, and the user is redirected back to "/". But, if the user tries to access "/login" directly, or any other route such as "/options", "/profile", etc.. I have tried to use some kind of regex, but could not figure it out unfortunately, and resulted in an infinite redirect to "/index.html/index.html..." until the browser blocked the redirect.
Here is my attempt: I added this location to the end of config:
location ~* ^/(.*) {
index /home/projects/myproject/vue/dist/index.html;
}
CodePudding user response:
Lets look at your try_files
directive:
try_files $uri $uri/ /home/projects/myproject/vue/dist/index.html =404;
So what happened here when your user tries to access the /login
URI directly?
nginx processed first
try_files
parameter$uri
(which is equals to/login
), tries to check the/home/projects/insights/vue/dist/login
file existence and fails;nginx processed second
try_files
parameter$uri/
, tries to check the/home/projects/insights/vue/dist/login/
directory existence and fails;nginx processed third
try_files
parameter/home/projects/myproject/vue/dist/index.html
, tries to check the/home/projects/insights/vue/dist/home/projects/myproject/vue/dist/index.html
file existence and fails;nginx returns HTTP 404 Not Found code.
As it stated by the documentation, last parameter of the try_files
directive can be
- a new URI;
- HTTP error code:
=code
; - named location ID:
@location_name
.
You need to process all requests for the non-existed files with your Vue app index.html
file, so change your try_files
directive to use /index.html
as new URI if all other checks fails:
try_files $uri $uri/ /index.html;
(and I'm not sure you need that $uri/
part at all, maybe just try_files $uri /index.html;
would be enough).
Additionally, I recommend you to use root /home/projects/myproject
instead of alias /home/projects/myproject/static/
and alias /home/projects/myproject/media/
directives. As it said by the alias
directive documentation:
When location matches the last part of the directive’s value:
location /images/ { alias /data/w3/images/; }
it is better to use the root directive instead:
location /images/ { root /data/w3; }
That way you can simplify your configuration to
server {
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /home/projects/myproject/ssl/ANY.serverurl.com.crt;
ssl_certificate_key /home/projects/myproject/ssl/ANY.serverurl.com.key;
server_name serverurl.com www.serverurl.com;
access_log /home/projects/myproject/logs/nginx_access.log;
error_log /home/projects/myproject/logs/nginx_error.log;
root /home/projects/myproject;
location / {
root /home/projects/insights/vue/dist;
try_files $uri /index.html;
}
location /backend/ {
include /etc/nginx/uwsgi_params;
uwsgi_pass myproject;
}
location /static/ {}
location /media/ {}
}