Try_files and location blocks

António P. P. Almeida appa at perusio.net
Fri Jun 24 02:02:06 MSD 2011


On 23 Jun 2011 22h37 WEST, dave at jetcafe.org wrote:

> Hello. :) Could someone please correct my understanding of location
> blocks and try files? I'm trying to get http errors to be very
> graceful, normally being handled by php but in extreme cases
> returning the proper numeric error. For my example, just consider
> 404:

My take on it.

> server {
> ...
> try_files $uri $uri/ /error.php?c=404
>
> error_page 404 = @error_404;
> location @error_404 {
> try_files /error.php @not_found;
> rewrite ^ $scheme://$server_name/error.php?c=404
> }
> location @not_found {
> return 404;
> }
> }

There are no "regular" locations, meaning, regex or others. Only
"special" named locations. They must be invoked explicitly in your
config.

NGX_HTTP_TRY_FILES_PHASE happens at server level. Tries to serve the requested
URI either as a file or a dir. Fallbacks to error.php with arg c=404;

If the file is not found then signals a 404, error_page directive
redirects to @error_404 location.

@error_404 location runs rewrite phase directive, rewriting to 
 $scheme://$server_name/error.php?c=404

Try files phase runs again and serves the URI /error.php with arg c=404.

> I'm not clear why this does not work. I rewrite the above example
> as:
>
> server {
> ...
> location / {
> try_files $uri $uri/ /error.php?c=404;
> }	  
>
> location /error.php {
> try_files /error.php @not_found;
> }
>
> error_page 404 = @not_found;
> location @not_found {
> return 404;
> }
> }

Now the processing will try to find a matching location. If none is
found than use the '/' "catch-all" location.

Any URI != error.php will be served by handlers you have specified in
the '/' location and those that are inherited from outside (the rule
with some exceptions).

In this case runs the try_files directive like above, fallbacks to
error.php with arg c=404. 

Now enters /error.php location, runs try_files again, tries error.php
fallbacks to @not_found. Location @not_found runs rewrite phase
directive return 404. Status 404 is returned. No more processing here.  

Note that the error_page directive is only invoked if you don't have
the error.php file in place. Otherwise it will never run.

> and it appears to work. I think the downside of this is that 
> I have to have the location /error.php explicitly invoke php.
>
> While I enjoy hacking at something, I also enjoy understanding
> something just as well. So what am I confused about?

HTH,
--- appa

PS: You can verify this flow in your error log by using the debug flag
    with the error_log directive.



More information about the nginx mailing list