Nginx – Strange behavior with nginx try_files. What’s wrong in the config

nginxreverse-proxy

os: debian stable (squeeze)
nginx: squeeze-backports 1.2.1-2~bpo60+1

try_files just behave strange to me.

this works as expected, $uri is tried localy if not found -> the @static location is used

try_files  $uri $uri/ @static;

just adding a =404 to the end leads to a 404. shouldn't it still work if i access a existing file which is located $uri or @static, and only serve a 404 if nothing is found on the @static location?

try_files  $uri $uri/ @static =404;

putting the =404 before the @static makes it work again. why?
if the file is not located at the $uri or $uri/ location but on @static it should lead to 404 because =404 is befor the @static (for my understanding). if i put access a file which is located at $uri it is correctly served from nginx (not hitting the @static backend or the =404)

try_files  $uri $uri/ =404 @static ;

i am quite confused

edit: my goal would be: test if the file is locally, then check all upstream servers for the file and if not found on these locations return a 404

config:

upstream domain.com_upstream
{
    server yyy.yyy.yyy.yyy:8000 weight=10 max_fails=3 fail_timeout=3s;
    server zzz.zzz.zzz.zzz:8020 weight=10 max_fails=3 fail_timeout=3s;
}

server 
{
    server_name         www.domain.com;

    listen              xxx.xxx.xxx.xxx:80;

    location @static
    {
        proxy_ignore_client_abort off;
        proxy_intercept_errors    on;
        proxy_next_upstream       http_404 error timeout invalid_header;

        proxy_pass                  http://domain.com_upstream;
        proxy_redirect              off;
        proxy_set_header            Host                $host;
        proxy_set_header            X-Real-IP           $remote_addr;
        proxy_set_header            X-Forwarded-For     $proxy_add_x_forwarded_for;
        client_max_body_size        10m;
        client_body_buffer_size     128k;

        proxy_connect_timeout       10;
        proxy_send_timeout          120;
        proxy_read_timeout          120;

        proxy_buffers 8 16k;
        proxy_buffer_size 32k;
    }

    location ~ ^/test 
    { 
        root /var/www/test;
        try_files $uri @static =404; # exchange with upper try_file examples...
    }

    *** snip ***
}

Best Answer

You misunderstood try_files parameters. Quote from docs:

If none of the files were found, an internal redirect to the uri specified by the last parameter is made.

Only the last parameter is a fallback URI (or a named location, or a code), all other parameters are files to test. I.e.

try_files /file1 /file2 /file3 ... @fallback;

will check for files under the document root (/file1, /file2, /file3 and so on), and if nothing found nginx will do an internal redirect to a @fallback.

The try_files ... @static =404; doesn't really make sense as it will test for a file named @static under the document root, and most likely it's not what you want. The try_files ... =404 @static; doesn't make sense, too, as it will test for a file named =404.

See here for docs: http://nginx.org/r/try_files.