24

I have create a simple Nginx config file to server an Angular like so:

server {
  listen 80;
  listen [::]:80;

  root /path/to/apps/myapp/current/dist;
  access_log /path/to/apps/myapp/current/log/nginx.access.log;
  error_log /path/to/apps/myapp/current/log/nginx.error.log info;

  index index.html;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  location / {
    try_files $uri $uri/ =404;
  }
}

And all works fine as expected. because I'm using Angular UI Router, I'd like to forward all pages to index.html so Angular will take over (so a request to example.com/users/new will be redirect by Nginx to index.html, for Angular UI to handle it) for pages reloads, links, etc.

How can I achieve this?

I've playing around with options like:

server {
    #implemented by default, change if you need different ip or port
    #listen *:80 | *:8000;
    server_name test.com;
    return 301 $scheme://www.test.com$request_uri;
}

As specified in this answer. But I couldn't anything similar to work based on all requests.

Suggestions will be much appreciated.

Community
  • 1
  • 1
WagnerMatosUK
  • 4,309
  • 7
  • 56
  • 95

3 Answers3

31

You've nearly got it. try_files is the correct one to use, as Richard shows, you just needed to add your index.html in the list. However, there is no need to remove the =404 from the end, in fact, its better not to.

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

Once the above change is implemented, reload the config with sudo nginx -s reload

  • $uri will try the request as a file, if this fails, it moves to the next one.
  • $uri/ will try the request as a folder /index.html will then be tried, which sends all requests to your index.html where your angular app will be able to route things (also make sure you use html5mode to avoid the use of # in the url.
  • =404 will be your final fallback, basically saying: I've tried this as a file, folder, and via index.html. If index.html fails/does not exist for whatever reason, we will serve a 404 error.

Why =404?

If all goes well, the last one is never used, and routing will just try file, folder, angular app. And that would be it. But I see it as good practice to have the =404 on the end to cover all bases.

Important note about index.html catchall

Regardless of whether or not you use the =404 in try_files, by directing everything to index.html, you basically lose the ability to serve 404 errors from your webserver, unless index.html does not exist (which is where =404 comes in). This means that you will need to handle 'Not Found' urls and missing pages within Angular JS, and you need to be ok with the fact that the error page you use will return a HTTP 200 response, rather than 404. (This is because the moment you direct to the index.html, you've served a page to the user, thus 200).

For added reassurance on the above, google try_files angular js and you will find most examples incorporate =404.

References:

redfox05
  • 3,354
  • 1
  • 34
  • 39
24

You need to add the router to the end of your try_files directive, like this:

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

See this document for more.

Richard Smith
  • 45,711
  • 6
  • 82
  • 81
  • 1
    Unfortunately that didn't work. When I tried to reload the page or follow a link I got a 404 – WagnerMatosUK Jan 29 '16 at 17:18
  • This works, he probably just needed to restart nginx. – Justin Feb 28 '17 at 02:47
  • I'd say you need =404 on the end too, as a final fallback – redfox05 Nov 30 '17 at 20:41
  • @redfox05 Try_files can only accept one default action as the last parameter. Use a response code or a URI not both. See link added to my answer. – Richard Smith Nov 30 '17 at 21:12
  • I think you misunderstood my point. The =404 on the end is a final fallback. It will try each option in turn, and not go further if it succeeds. Best explained with an example. I'll add it as an answer. – redfox05 Dec 21 '17 at 17:31
  • @RichardSmith just to follow up, as its showing people are still looking at this question, the document you linked literally shows an example with uri's and response codes. Quote: `The last parameter can also point to a named location, as shown in examples below. Starting from version 0.7.51, the last parameter can also be a code: location / { try_files $uri $uri/index.html $uri.html =404; }` – redfox05 Feb 22 '19 at 23:10
  • That is not the same. In your answer the =404 can never be reached unless the index is deleted for some reason in which case you have bigger problems to sort out. – Richard Smith Feb 22 '19 at 23:22
0
   location / {
         
           try_files $uri$args $uri$args/ index.html;
          
        }

This worked for me

Sachin
  • 11
  • 5