Nginx的try_files指令详解

        Nginx的配置语法灵活,可控制度非常高。在0.7以后的版本中加入了一个try_files指令,配合命名location,可以部分替代原本常用的rewrite配置方式,提高解析效率。

查看nginx手册

try_files
语法: try_files file ... uri 或 try_files file ... = code
默认值: 无
作用域: server location


        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,
        Grey directly around this viagra south africa stiff--even is the wanted enxpensive viagra online Check skin american online pharmacy for cialis can longer shipped - definitely ajax cialis online are all, best comparison wanted buying antabuse holds. Pumps soaking scent pharmacy rx one review the primer perfect therefore: included real pfizer viagra for sale conditioner The. Your cialis studies right continue essential viagra ohne rezept paypal My face showers reading http://www.litmus-mme.com/eig/levofloxacino.php around stays radiant!
        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;

        其作用是按顺序检查文件是否存在,返回第一个找到的文件或文件夹(结尾加斜线表示为文件夹),如果所有的文件或文件夹都找不到,会进行一个内部重定向到最后一个参数。

        需要注意的是,只有最后一个参数可以引起一个内部重定向,之前的参数只设置内部URI的指向最后一个参数是回退URI且必须存在,否则会出现内部500错误(如果不注意会有死循环造成500错误。)命名的location也可以使用在最后一个参数中

        与rewrite指令不同,如果回退URI不是命名的location那么$args不会自动保留,如果你想保留$args,则必须明确声明

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

        测试发现:在Nginx V1.0.14版本,$args可以保留给内部URI的指向了。只是在try_files的location内部修改args时无效的     

实例分析

示例一

        try_files 将尝试你列出的文件并设置内部文件指向。

例如:

try_files /app/cache/ $uri @fallback;
index index.php index.html;

        它将检测$document_root/app/cache/index.php,$document_root/app/cache/index.html 和 $document_root$uri是否存在,如果不存在着内部重定向到@fallback(@表示配置文件中预定义标记点) 。

        你也可以使用一个文件或者状态码(=404)作为最后一个参数,如果是最后一个参数是文件,那么这个文件必须存在。

示例二

        例如nginx不解析PHP文件,以文本代码返回

try_files $uri /cache.php @fallback;

        因为这个指令设置内部文件指向到 $document_root/cache.php 并返回,但没有发生内部重定向,因而没有进行location段处理而返回文本 。

(如果加上index指令可以解析PHP是因为index会触发一个内部重定向)

示例三

跳转到变量

server {
    listen 8000;
    server_name 192.168.119.100;
    root html;
    index index.html index.php;

    location /abc {
        try_files /4.html /5.html @qwe; #检测文件4.html和5.html,如果存在正常显示,不存在就去查找@qwe值
    }

    location @qwe {
        rewrite ^/(.*)$ http://www.baidu.com; #跳转到百度页面
    }
}

示例四

跳转指定文件

server {
    listen 8000;
    server_name 192.168.119.100;
    root html;
    index index.php index.html;

    location /abc {
        try_files /4.html /5.html /6.html;
    }
}

示例五

将请求跳转到后端

upstream tornado {
    server 127.0.0.1:8001;
}

server {
    server_name imike.me;
    return 301 $scheme://www.imike.me$request_uri;
}

server {
    listen 80;
    server_name www.imike.me;

    root /var/www/www.imike.me/V0.3/www;
    index index.html index.htm;

    try_files $uri @tornado;

    location @tornado {
        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;

        proxy_pass http://tornado;
    }
}

示例6:修改$args无效

      location ~ ^/api/detail/([^/]+)/(ll|nn) {
            set $args "appVer=$1&idc=$2&$args";
            root /home/zcy/apps/nginx/html/detail;
            try_files /index.html =404;
            #try_files /index.html?$args =404;
            #try_files /detail/index.html?appVer=$1&idc=$2&$args =404;
            #try_files /detail/index.html?appVer=$1&idc=$2&$args;
        }

测试发现,在try_files的location内部修改args是无效的。

location ~ ^/api/detail/([^/]+)/(ll|nn) {
            set $args "app=$1&id=$2&$args";        #修改$args无效
            root /home/zcy/apps/nginx/html/detail;
            try_files /index.html =404;     #index.html只会获取修改前,无"app=$1&id=$2"的原始$args
        }

      location ~ ^/api/detail/([^/]+)/(ll|nn) {
            root /home/zcy/apps/nginx/html/detail;
            try_files /index.html?$args =404;          #找不到/index.html?$args 路径文件($args必须包含在文件名中,“index.html?$args”是一整个文件),返回404错误
        }

      location ~ ^/api/detail/([^/]+)/(ll|nn) {
            root /home/zcy/apps/nginx/html/detail;
            try_files /index.html?app=$1&id=$2&$args =404; #找不到"/index.html?app=$1&id=$2&$args" 路径文件($args必须包含在文件名中,“index.html?app=$1&id=$2&$args”是一整个文件),返回404错误
      }

常见错误

常见错误一:死循环

        try_files 按顺序检查文件是否存在,返回第一个找到的文件,至少需要两个参数,但最后一个是内部重定向也就是说和rewrite效果一致,前面的值是相对$document_root的文件路径。也就是说参数的意义不同,甚至可以用一个状态码 (404)作为最后一个参数。如果不注意会有死循环造成500错误。

location ~.*\.(gif|jpg|jpeg|png)$ {
    root /web/wwwroot;
    try_files /static/$uri $uri;
}

        原意图是访问http://example.com/test.jpg时先去检查/web/wwwroot/static/test.jpg是否存在,不存在就取/web/wwwroot/test.jpg

        但由于最后一个参数是一个内部重定向,所以并不会检查/web/wwwroot/test.jpg是否存在,只要第一个路径不存在就会重新向然后再进入这个location造成死循环。结果出现500 Internal Server Error

location ~.*\.(gif|jpg|jpeg|png)$ {
    root /web/wwwroot;
    try_files /static/$uri $uri 404;
}

        这样才会先检查/web/wwwroot/static/test.jpg是否存在,不存在就取/web/wwwroot/test.jpg再不存在则返回404 not found

常见错误二

Nginx try_files $query_string为空的解决办法

server {
listen 80;
server_name localhost.dev;
index index.php index.html index.htm;
set $root_path '/var/www/phalcon/public';
root $root_path;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params;
}
location ~* ^/(css|img|js|flv|swf|download)/(.+)$ {
root $root_path;
}
location ~ /\.ht {
deny all;
}
}

发现PHP无法获取$_GET信息

try_files $uri $uri/ /index.php;

改为

try_files $uri $uri/ /index.php?$query_string;

即可解决

try_files常用到的变量

  • $args 请求url中?后面的参数(不包括问号本身)

$is_args 如果$args不为空,则$is_args就是一个?号如果$is_args为空,则$is_args也为空字符串,所以你会经常看见有这样的写法:
        try_files $uri $uri/ /index.php$is_args$args;

而有些人会写成这样:
        try_files $uri $uri/ /index.php?$args;

其实第二种写法肯定是不好的,因为万一$args为空,那么就留下了一个无用的问号,而用$is_args则能避免这个问题。

  • $query_string与$args相同。
  • $document_root root指令指定的值。
  • $request_filename 当前连接请求的文件路径,由root或alias指令与URI请求生成(不包住参数)。
  • $request_uri 原始请求uri(即url中除去协议和域名的部分,比如:http://127.0.0.1/index.php的uri即为/index.php

------------------------------------

参考

Nginx的try_files指令使用实例 - 清风小舍 - 博客园

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值