[edit] try_files

Syntax: try_files file ... uri
try_files file ... = code
Default:
Context: server
location
Reference: try_files


Checks for the existence of files in order, and returns the first file that is found. A trailing slash indicates a directory - $uri /. In the event that no file is found, an internal redirect to the last parameter is invoked. Do note that only the last parameter causes an internal redirect, former ones just sets the internal URI pointer. The last parameter is the fallback URI and *must* exist, or else an internal error will be raised. Named locations can be used. Unlike with rewrite, $args are not automatically preserved if the fallback is not a named location. If you need args preserved, you must do so explicitly:

try_files $uri $uri/ /index.php?q=$uri&$args;

Example use in proxying Mongrel:

try_files /system/maintenance.html $uri $uri/index.html $uri.html @mongrel;
 
location @mongrel {
  proxy_pass http://mongrel;
}

Note that you can specify an HTTP status code as the last argument to try_file since Nginx version 0.7.51. Here's an example:

location / {
  try_files $uri $uri/ /error.php?c=404 =404;
}

When all other attempts to serve the content corresponding to the request fail issue a 404 Not Found.


Example of use with Drupal / FastCGI:

# for Drupal 6 or 7:
try_files $uri $uri/ /index.php?q=$uri&$args;
 
# a better version for Drupal 7 since it doesn't need q=$uri:
try_files $uri $uri/ /index.php?$args;
 
location ~ \.php$ {
  fastcgi_pass 127.0.0.1:8888;
  fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name; # if not already defined in the fastcgi_params file
  # any other specific fastcgi_params
}

In this example, the directive try_files

try_files $uri $uri/ /index.php?q=$uri&$args;

Is basically the same as this:

location / {
  error_page     404 = @drupal;
  log_not_found  off;
}
 
location @drupal {
  rewrite ^ /index.php?q=$uri last; # for drupal 6
}

Or this:

# DO NOT DO THIS! This is a terrible use of if.
if (!-e $request_filename) {
   rewrite ^ /index.php?q=$uri last;
}

try_files is basically a replacement for the typical mod_rewrite style file/directory existence check. It is supposed to be more efficient than using if - see IfIsEvil

Examples of use with Wordpress and Joomla (typical "Front controller pattern" packages)

# wordpress (without WP Super Cache) - example 1
try_files $uri $uri/ /index.php?q=$uri&$args;
 
# wordpress (without WP Super Cache) - example 2 
# It doesn't REALLY need the "q" parameter, but without an explicit $args php 
# gets an empty QUERY_STRING, breaking generated responses that don't use a 
# permalink, such as search results.
try_files $uri $uri/ /index.php?$args;
 
# joomla
try_files $uri $uri/ /index.php?q=$uri&$args;
 
location ~ \.php$ {
  fastcgi_pass 127.0.0.1:8888;
  fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name; # if not already defined in the fastcgi_params file
  # any other specific fastcgi_params
}

WP Super Cache requires a bunch of static file checks. Those are not shown here.


Module: HttpCoreModule