Hello!
On Tue, Dec 07, 2010 at 01:43:16PM -0800, [email protected] wrote:
try_files $uri /testing/oops.png;
statement is actually doing.
What “if” statement (inside location) actually doing is creating
implicit nested location (conditional one), with some hacks to
make handler modules (proxy_pass, fastcgi_pass, …) to be
inherited into this location (normally they aren’t). Basically
there are two problems:
- People expect
location / {
set $true 1;
if ($true) {
add_header X-Header-One 1;
}
if ($true) {
add_header X-Header-Two 2;
}
}
to return both headers. Though this isn’t something going to
happen, as actually the above config means something like
location / {
location …implicit-location-1 {
add_header X-Header-One 1;
}
location ...implicit-location-2 {
add_header X-Header-Two 2;
}
}
And as usual nginx will select only one location to process
request. Hence only X-Header-Two will be returned.
- Mentioned hacks are incomplete / broken and may cause various
problems. As in your case - they don’t handle try_files (which
isn’t normally inherited, too). E.g. something like
location / {
try_files /file @fallback;
set $true 1;
if ($true) {
# nothing
}
}
is actually means for nginx something like
location / {
try_files /file @fallback;
location ...implicit-location-which-matches-everything {
# no try_files here
}
}
and try_files will not work - as there is no try_files in location
which actually used to process request.
More cases are listed on If is Evil… when used in location context | NGINX.
following:
}
This is clever! I didn’t know you could set an internal location with
error_page. Not that it isn’t documented, just that I never even
considered looking there for that sort of thing since the case I’m
using it for is not an error.
One more hint: using “error_page fallback” like
log_not_found off;
error_page 404 = @fallback;
is actually better than try_files in simple cases. It a) saves
one stat() syscall and b) isn’t racy (try_files aproach has race
between stat() and then open() in static handler, which makes it
possible to generate 404 anyway - if you happen to delete file
between stat() and open()).
On the other hand - try_files is easier to use, especially
in complex cases.
Maxim D.