try_files ignored in combination with error_page and named locations
Ruslan Ermilov
ru at nginx.com
Wed Apr 4 08:16:10 UTC 2012
On Tue, Apr 03, 2012 at 10:30:39PM +0200, Džen wrote:
> For some reason the following nginx configuration snippet doesn't work
> as expected, try_files seems to be ignored. When / is requested (or any
> other URI which points to a file which doesn't exist), nginx's default
> 503 page is returned instead of the existing index.html. Requesting
> /index.html works correctly.
>
> location @maintenance {
> root /var/nginx/$hostid-maintenance;
> index index.html;
> try_files $uri $uri/ / =500;
> }
>
> error_page 503 @maintenance;
>
> if ( -d $document_root/$hostid-maintenance ) {
> return 503;
> }
>
> Any thoughts? Running nginx version 1.0.12 here.
First, this is a wacky config, and I don't quite understand what
you're trying to achieve with it. :)
Here's what happens with the request of "/", assuming that "if"
condition holds true.
The status code is set to 503, and further processing happends in
the named location @maintenance.
It tries "$uri", find that directory, but because argument does
not end with a slash (i.e., we're testing a file, not directory),
this variant is ignored.
It then tries "$uri/", and succeeds. $uri is set to
"/$hostid-maintenance/". As documentation of "try_files" says,
the further processing is done in thi same (named) location.
What happens next is since a request now ends with a slash, the
static module handler ignores it, and a request is processed by
the index module. The index module then verifies that the
"/var/nginx/$hostid-maintenance/index.html" file exists and does
an internal redirect to a new $uri. (The fact that it does an
internal redirect is also documented.)
This in turn gets processed by the server's default location
which is configured to return 503. Because
"recursive_error_pages" aren't enabled, the server ends up
returning status code 503 with the standard content.
(What happens when you enable is left as an excercise to a
reader.)
When OTOH you request "/index.html", try_files checks that the
_file_ exists, and the processing is performed by the static
module in the context of location @maintenance. There are no
more internal redirects involved, so the server ends up sending
you the status code 503 with the contents of index.html.
I agree that this might not be obvious, but this is how it works.
The important bit here is that requests that end up with "/", and
get processed by the index module, do an internal redirect. This
is quite logical if you think about it, because they *usually*
get processed by the static module, as if a request ended up with
"/" followed by the name of index file.
More information about the nginx
mailing list