Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle 404 error request in vuejs SPA with nginx server

I have set up my vue-cli version 3 SPA so that any requests not found in my routes.js file will default to my 404 view as shown in the official documentation:

Inserted near bottom of routes.js file:

{ // catches 404 errors
  path: '*',
  name: '404',
  component: () => import(/* webpackChunkName: "NotFoundComponent" */ './views/NotFoundComponent.vue'),
},

Inserted into nginx configuration file:

location / {
  try_files $uri $uri/ /index.html;
}

This successfully alerts the user that the page they requested doesn't exist.

My Question:

I would like for the error 404 component to return a 404 response header (it current returns the 200 status code) and also log this error to the nginx error.log file. I imagine this is only possible through using nginx configuration. Has anyone achieved this goal?

I noticed that this issue is addressed in the following page in the vue-cli official docs, but it only is concerned with node express servers and not nginx: https://router.vuejs.org/guide/essentials/history-mode.html#caveat

like image 831
GustavMahler Avatar asked Jan 01 '23 19:01

GustavMahler


2 Answers

I think it is similar to Node solution - you should repeat all your routes in nginx config to return 404 status code correctly, the main idea is that you should use "equals" modifier in locations and define error_page to return same index.html file but with 404 status code, example:

server {
    listen       80;
    server_name  localhost;
    root /my/dir/with/app
    error_page  404 /index.html;

    location = / {
        try_files $uri $uri/ /index.html;
    }

    location = /books {
        try_files $uri $uri/ /index.html;
    }

    # example nested page
    location = /books/authors {
        try_files $uri $uri/ /index.html;
    }

    # example dynamic route to access book by id
    location ~ /books/\d+$ {
        try_files $uri $uri/ /index.html;
    }
}

Probably this config can be simplified or improved because I am not very good at nginx configuration but it works.

like image 174
Max Sinev Avatar answered Jan 05 '23 14:01

Max Sinev


I solved this the easy way by breaking out of the Vue ecosystem else it wont work or would take a lot of effort.

Make the following route in your Vue router:

{
  path: '*',
  name: 'PageNotFound',
  component: PageNotFound
}

The PageNotFound component should have the following code:

<script>
export default {
  name: 'PageNotFound',
  created() {
    window.location.href = "/404/"
  }
}
</script>

The nginx config should return a 404 on getting /404/ route:

server {
    ...
    location ~ ^/404/$ {
        return 404;
    }
    ...
}

I don't think it would work in a server side rendering environment. In such a case you might need to put the statement containing window.location.href in the mounted method.

like image 29
Compro Prasad Avatar answered Jan 05 '23 15:01

Compro Prasad