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_filesparameter$uri(which is equals to/login), tries to check the/home/projects/insights/vue/dist/loginfile existence and fails;nginx processed second
try_filesparameter$uri/, tries to check the/home/projects/insights/vue/dist/login/directory existence and fails;nginx processed third
try_filesparameter/home/projects/myproject/vue/dist/index.html, tries to check the/home/projects/insights/vue/dist/home/projects/myproject/vue/dist/index.htmlfile 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/ {}
}
