Home > Net >  NginX location management with Django&Vue.js setup
NginX location management with Django&Vue.js setup

Time:10-20

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?

  1. 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;

  2. nginx processed second try_files parameter $uri/, tries to check the /home/projects/insights/vue/dist/login/ directory existence and fails;

  3. 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;

  4. 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/ {}
}
  • Related