Strange results when chaining try_files

Maxim Dounin mdounin at mdounin.ru
Sun Nov 8 14:40:35 MSK 2009


Hello!

On Sun, Nov 08, 2009 at 09:11:28PM +1100, Jeff Waugh wrote:

> Hi all,
> 
> Wondering if anyone can explain what's going on here... I'm trying to come
> up with a "more perfect" WordPress + WP-Super-Cache configuration, using
> try_files to fall back through static files, cached files and finally, the
> dynamic script... the challenge is the preconditions on the use of the on
> disk cached files (checking cookies and so on).
> 
> Here's a summary of the virtual host's configuration:
> 
>   server {
>     listen  80;
>     server_name  trunk.press.home;
>     root  /srv/wordpress/trunk;
>     index  index.php;
> 
>     access_log  /var/log/nginx/access.log;
>     error_log  /var/log/nginx/error.log  notice;
>     rewrite_log  on;
> 
>     location / {
>       try_files  $uri  @supercache;
>       # ultimately this would have more in it, but I have
>       # stripped it down to clarify the test case
>     }
> 
>     location @supercache {
>       set  $idx  'index.html';
>       set $supercache '/wp-content/cache/supercache/$host$request_uri$idx';
>       # ^ nasty, but it's because I can't do $request_uriindex.html :-)

Just a side note: ${request_uri}index.html should do the trick.

> 
>       if ( $http_cookie ~* wordpress ) {
>         set  $supercache  '';
>         break;
>       }
> 
>       try_files  $supercache  /index.php;
>     }
> 
>     location ~ \.php$ {
>       # totally normal, working fastcgi configuration
>     }
>   }
> 
> A no-cookie request to http://trunk.press.home/ and /about/ works fine. A
> request to / with the cookie works fine. However, a request to /about/ with
> the cookie returns a 404.
> 
> Here's what the logs show:
> 
>   [notice] 28051#0: *21690 "wordpress" matches "wordpress=true", client:
>   192.168.10.121, server: trunk.press.home, request: "GET /about/ HTTP/1.1",
>   host: "trunk.press.home"
> 
>   [error] 28051#0: *21690 "/srv/wordpress/trunk/about/index.php" is not
>   found (2: No such file or directory), client: 192.168.10.121, server:
>   trunk.press.home, request: "GET /about/ HTTP/1.1", host:
>   "trunk.press.home"
> 
> It's that second error which surprises me -- why, with the cookie, is the
> ultimate request going to /trunk/about/index.php, not /trunk/index.php? AND,
> if I change the index to index.html, it'll fail looking for THAT (ie. this
> is not a result of the try_files in @supercache).
> 
> This fails even if I set $supercache to a nonsense file rather than a blank
> string.
> 
> Thoughts?

Well, it sounds somewhat funny.  You tried to rewrite config to 
use try_files instead of if's and fall into one of if tarpits.  :)

In this particular case try_files isn't inherited into implicit 
location created by if, and therefore doesn't work.  Reduced 
test-case as have it in my collection "why if is evil" is:

        # try_files wont work due to if

        location /if-try-files {
             try_files  /file  @fallback;

             set $true 1;

             if ($true) {
                 # nothing
             }
        }

There are two possible solutions: either move if() to server{} 
level, or go to another explicit location in if() (via "rewrite ... 
last" or "return ...").

Something like this should work:

    location @supercache {
        error_page 404 = /index.php;

        if ($http_cookie ~* wordpress) {
            return 404;
        }

        try_files  /path/to/check  /index.php;
    }

[just a usual disclaimer]

If is evil.  If you use if() in your config - prepare for fun.  
The are only 2 things that can be safely done within an if() in 
location:

1. rewrite ... last;

2. return ...;

[end of disclaimer]

Maxim Dounin





More information about the nginx mailing list