您的位置:

nginxtry_files详解

一、try_files概述

try_files是nginx中一个非常重要的指令,用于指定nginx在查找静态文件时的顺序。其语法为:

try_files file ... uri;

其中file表示nginx查找文件的路径,可以指定多个路径,以空格分隔。uri表示启用动态页面请求的URI地址。当nginx遇到需要查找静态文件的请求时,它会按照指定的file顺序查找文件,如果查找到了,nginx会直接返回响应,否则nginx会请求uri对应的动态页面。

二、try_files常见使用场景

1、前端路由处理:

location / {
    try_files $uri $uri/ /index.html;
    # $uri指请求的uri路径,$uri/表示请求的uri路径加上一个/,例如访问example.com/path,则会依次尝试访问/path,/path/index.html,/index.html
    # /index.html表示如果仍未匹配到则重定向到index.html
}

这种场景多用于单页应用,例如vue.js等前端框架的路由管理。当用户在浏览器中访问一个非根路径的路径时,由于这些路径都是由前端路由管理的,nginx无法直接返回正确的静态文件,因此需要将请求重定向到统一的路径,这里是/index.html,由前端路由控制页面的展示。

2、图片服务器:

location /images/ {
  root /data/www;
  error_page 404 = /fetch_image.php;
  try_files $uri $uri/ =404;
}
location /fetch_image.php {
  fastcgi_pass 127.0.0.1:9000;
  set $path_info "";
  fastcgi_param PATH_INFO $path_info;
  fastcgi_param SCRIPT_FILENAME /scripts/fetch_image.php;
  include fastcgi_params;
}

这种场景多用于图片服务器,当用户访问图片时,先尝试在本地文件系统中查找是否有该文件,如果找到就返回;如果没有找到则会转发到fetch_image.php进行处理,从远程资源服务器拉取图片并返回给用户。

三、try_files注意事项

1、路径匹配规则:try_files会按照给定的路径参数逐一进行查找,如果路径中提供了/,则nginx会认为它是一个绝对路径,并直接将其与root指令中指定的路径进行拼接;如果路径中没有/,则nginx会认为它是一个相对路径,并将其与当前请求的URI进行拼接,再与root指令中指定的路径进行拼接。例如:

location / {
    root /data/www;
    try_files test.html /test.html;
    # 当请求example.com/时,nginx会依次尝试访问/data/www/test.html、/data/www/test.html/index.html和/data/www/index.html,如果都没有找到则会返回404
}

2、设置HTTP头:如果设置了try_files,可能会影响HTTP头中的Content-Type和Content-Length,因此需要在配置文件中设置正确的HTTP头。

location /images/ {
    root /data/images;
    try_files $uri /fallback.png;
    add_header Content-Type image/png;
}

四、try_files示例代码

# 示例1:前端路由处理
location / {
    try_files $uri $uri/ /index.html;
}

# 示例2:图片服务器
location /images/ {
  root /data/www;
  error_page 404 = /fetch_image.php;
  try_files $uri $uri/ =404;
}
location /fetch_image.php {
  fastcgi_pass 127.0.0.1:9000;
  set $path_info "";
  fastcgi_param PATH_INFO $path_info;
  fastcgi_param SCRIPT_FILENAME /scripts/fetch_image.php;
  include fastcgi_params;
}

# 示例3:设置HTTP头
location /images/ {
    root /data/images;
    try_files $uri /fallback.png;
    add_header Content-Type image/png;
}