Strange results when chaining try_files

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 :slight_smile:

  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?

  • Jeff

Hello!

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

server {
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.

  # totally normal, working fastcgi configuration

192.168.10.121, server: trunk.press.home, request: “GET /about/ HTTP/1.1”,
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. :slight_smile:

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 D.

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

Ah, nice! Thanks.

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. :slight_smile:

Good lord. :wink: Thanks heaps for your explanation – looks like using
rewrite
for the supercache file ends up being the neatest solution… the
error_page
one just feels icky to me. :slight_smile:

(If ever there were a list of posts documenting the “Zen of Nginx”, this
one
easily qualifies!)

Thanks again,

  • Jeff