Nginx 配置指令的执行顺序(十一)

紧跟在 post-access 阶段之后的是 try-files 阶段。这个阶段专门用于实现标准配置指令 try_files 的功能,并不支持 Nginx 模块注册处理程序。由于 try_files 指令在许多 FastCGI 应用的配置中都有用到,所以我们不妨在这里简单介绍一下。

try_files 指令接受两个以上任意数量的参数,每个参数都指定了一个 URI. 这里假设配置了 N 个参数,则 Nginx 会在 try-files 阶段,依次把前 N-1 个参数映射为文件系统上的对象(文件或者目录),然后检查这些对象是否存在。一旦 Nginx 发现某个文件系统对象存在,就会在 try-files 阶段把当前请求的 URI 改写为该对象所对应的参数 URI(但不会包含末尾的斜杠字符,也不会发生 “内部跳转”)。如果前 N-1 个参数所对应的文件系统对象都不存在,try-files 阶段就会立即发起“内部跳转”到最后一个参数(即第 N 个参数)所指定的 URI.

前面在 (六) 和 (七) 中已经看到静态资源服务模块会把当前请求的 URI 映射到文件系统,通过 root配置指令所指定的“文档根目录”进行映射。例如,当“文档根目录”是 /var/www/ 的时候,请求 URI/foo/bar 会被映射为文件 /var/www/foo/bar,而请求 URI /foo/baz/ 则会被映射为目录 /var/www/foo/baz/. 注意这里是如何通过 URI 末尾的斜杠字符是否存在来区分“目录”和“文件”的。我们正在讨论的 try_files配置指令使用同样的规则来完成其各个参数 URI 到文件系统对象的映射。

不妨来看下面这个例子:

    root /var/www/;     location /test {        try_files /foo /bar/ /baz;        echo "uri: $uri";    }     location /foo {        echo foo;    }     location /bar/ {        echo bar;    }     location /baz {        echo baz;    }

这里通过 root 指令把“文档根目录”配置为 /var/www/,如果你系统中的 /var/www/ 路径下存放有重要数据,则可以把它替换为其他任意路径,但此路径对运行 Nginx worker 进程的系统帐号至少有可读权限。我们在location /test 中使用了 try_files 配置指令,并提供了三个参数,/foo/bar/ 和 /baz. 根据前面对try_files 指令的介绍,我们可以知道,它会在 try-files 阶段依次检查前两个参数 /foo 和 /bar/ 所对应的文件系统对象是否存在。

不妨先来做一组实验。假设现在 /var/www/ 路径下是空的,则第一个参数 /foo 映射成的文件/var/www/foo 是不存在的;同样,对于第二个参数 /bar/ 所映射成的目录 /var/www/bar/ 也是不存在的。于是此时 Nginx 会在 try-files 阶段发起到最后一个参数所指定的 URI(即 /baz)的“内部跳转”。实际的请求结果证实了这一点:

    $ curl localhost:8080/test    baz

显然,该请求最终和 location /baz 绑定在一起,执行了输出 baz 字符串的工作。上例中定义的 location /foo 和 location /bar/ 完全不会参与这里的运行过程,因为对于 try_files 的前 N-1 个参数,Nginx 只会检查文件系统,而不会去执行 URI 与 location 之间的匹配。

对于上面这个请求,Nginx 会产生类似下面这样的“调试日志”:

    $ grep trying logs/error.log    [debug] 3869#0: *1 trying to use file: "/foo" "/var/www/foo"    [debug] 3869#0: *1 trying to use dir: "/bar" "/var/www/bar"    [debug] 3869#0: *1 trying to use file: "/baz" "/var/www/baz"

通过这些信息可以清楚地看到 try-files 阶段发生的事情:Nginx 依次检查了文件 /var/www/foo 和目录/var/www/bar,末了又处理了最后一个参数 /baz. 这里最后一条“调试信息”容易产生误解,会让人误以为 Nginx 也把最后一个参数 /baz 给映射成了文件系统对象进行检查,事实并非如此。当 try_files 指令处理到它的最后一个参数时,总是直接执行“内部跳转”,而不论其对应的文件系统对象是否存在。

接下来再做一组实验:在 /var/www/ 下创建一个名为 foo 的文件,其内容为 hello world(注意你需要有/var/www/ 目录下的写权限):

    $ echo ‘hello world‘ > /var/www/foo

然后再请求 /test 接口:

    $ curl localhost:8080/test    uri: /foo

这里发生了什么?我们来看,try_files 指令的第一个参数 /foo 可以映射为文件 /var/www/foo,而 Nginx 在try-files 阶段发现此文件确实存在,于是立即把当前请求的 URI 改写为这个参数的值,即 /foo,并且不再继续检查后面的参数,而直接运行后面的请求处理阶段。

上面这个请求在 try-files 阶段所产生的“调试日志”如下:

    $ grep trying logs/error.log    [debug] 4132#0: *1 trying to use file: "/foo" "/var/www/foo"

显然,在 try-files 阶段,Nginx 确实只检查和处理了 /foo 这一个参数,而后面的参数都被“短路”掉了。

类似地,假设我们删除刚才创建的 /var/www/foo 文件,而在 /var/www/ 下创建一个名为 bar 的子目录:

    $ mkdir /var/www/bar

则请求 /test 的结果也是类似的:

    $ curl localhost:8080/test    uri: /bar

在这种情况下,Nginx 在 try-files 阶段发现第一个参数 /foo 对应的文件不存在,就会转向检查第二个参数对应的文件系统对象(在这里便是目录 /var/www/bar/)。由于此目录存在,Nginx 就会把当前请求的 URI 改写为第二个参数的值,即 /bar(注意,原始参数值是 /bar/,但 try_files 会自动去除末尾的斜杠字符)。

这一组实验所产生的“调试日志”如下:

    $ grep trying logs/error.log    [debug] 4223#0: *1 trying to use file: "/foo" "/var/www/foo"    [debug] 4223#0: *1 trying to use dir: "/bar" "/var/www/bar"

我们看到,try_files 指令在这里只检查和处理了它的前两个参数。

通过前面这几组实验不难看到,try_files 指令本质上只是有条件地改写当前请求的 URI,而这里说的“条件”其实就是文件系统上的对象是否存在。当“条件”都不满足时,它就会无条件地发起一个指定的“内部跳转”。当然,除了无条件地发起“内部跳转”之外,try_files 指令还支持直接返回指定状态码的 HTTP 错误页,例如:

    try_files /foo /bar/ =404;

这行配置是说,当 /foo 和 /bar/ 参数所对应的文件系统对象都不存在时,就直接返回 404 Not Found 错误页。注意这里它是如何使用等号字符前缀来标识 HTTP 状态码的。

时间: 2024-10-09 16:16:57

Nginx 配置指令的执行顺序(十一)的相关文章

Nginx 配置指令的执行顺序(八)

前面我们详细讨论了 rewrite.access 和 content 这三个最为常见的 Nginx 请求处理阶段,在此过程中,也顺便介绍了运行在这三个阶段的众多 Nginx 模块及其配置指令.同时可以看到,请求处理阶段的划分直接影响到了配置指令的执行顺序,熟悉这些阶段对于正确配置不同的 Nginx 模块并实现它们彼此之间的协同工作是非常必要的.所以接下来我们接着讨论余下的那些阶段. 前面在 (一) 中提到,Nginx 处理请求的过程一共划分为 11 个阶段,按照执行顺序依次是 post-read

Nginx 配置指令的执行顺序(一)

大多数 Nginx 新手都会频繁遇到这样一个困惑,那就是当同一个 location 配置块使用了多个 Nginx 模块的配置指令时,这些指令的执行顺序很可能会跟它们的书写顺序大相径庭.于是许多人选择了“试错法”,然后他们的配置文件就时常被改得一片狼藉.这个系列的教程就旨在帮助读者逐步地理解这些配置指令背后的执行时间和先后顺序的奥秘. 现在就来看这样一个令人困惑的例子:     ? location /test {    ?     set $a 32;    ?     echo $a;    

Nginx 配置指令的执行顺序(二)

我们前面已经知道,当 set 指令用在 location 配置块中时,都是在当前请求的 rewrite 阶段运行的.事实上,在此上下文中,ngx_rewrite 模块中的几乎全部指令,都运行在 rewrite 阶段,包括 Nginx 变量漫谈(二) 中介绍过的 rewrite 指令.不过,值得一提的是,当这些指令使用在 server 配置块中时,则会运行在一个我们尚未提及的更早的处理阶段,server-rewrite 阶段. Nginx 变量漫谈(二) 中介绍过的 ngx_set_misc 模块

Nginx 配置指令的执行顺序(七)

来看一个 ngx_static 模块服务磁盘文件的例子.我们使用下面这个配置片段:     location / {        root /var/www/;    } 同时在本机的 /var/www/ 目录下创建两个文件,一个文件叫做 index.html,内容是一行文本 this is my home:另一个文件叫做 hello.html,内容是一行文本 hello world. 同时注意这两个文件的权限设置,确保它们都对运行 Nginx worker 进程的系统帐户可读. 现在来通过

NGINX openrestry(指令的执行顺序)

Nginx的指令的执行顺序: 一.post-read 二.server-rewrite ngx_rewrite模块的set指令和rewrite指令(前提在server里面配置时) 三.find-config 四.rewrite ngx_rewrite模块的set指令和rewrite指令(前提在location里面配置时) ngx_set_misc模块的set_unescape_uri指令 ngx_lua模块的set_by_lua指令 rewrite tail: ngx_headers_more模

Nginx 配置指令location 匹配符优先级和安全问题【转】

Nginx配置指令location匹配符优先级和安全问题 使用nginx 很久了,它的性能高,稳定性表现也很好,得到了很多人的认可.特别是它的配置,有点像写程序一样,每行命令结尾一个";"号,语句块用"{}"括起来.配制好,直接nginx -t 检查配制情况,配制成功,直接运行:service nginx reload.服务器没有任何宕机情况下,实现平稳修改配置.最近一直在做location 配置,遇到优先级别问题(如果配置不当可能存在安全隐患哦),以下是个人学习一

Nginx配置指令try_files

try_files指令是按顺序检测文件的存在性,并且返回第一个找到文件的内容,如果第一个找不到就会自动找第二个,依次查找.其实现的是内部跳转.以下举例说明: 案例1(跳转到变量): server {   listen 8000;   server_name 121.10.143.66;   root html;   index index.html index.php; location /abc { try_files /4.html /5.html @qwe;      --检测文件4.ht

转:Nginx配置指令location匹配符优先级和安全问题

转:http://www.jb51.net/article/47761.htm 使用nginx 很久了,它的性能高,稳定性表现也很好,得到了很多人的认可.特别是它的配置,有点像写程序一样,每行命令结尾一个";"号,语句块用"{}"括起来. 配制好,直接nginx -t 检查配制情况,配制成功,直接运行:service nginx reload .服务器没有任何宕机情况下,实现平稳修改配置 最近一直在做location 配置,遇到优先级别问题(如果配置不当可能存在安全

JFinal 配置类 方法执行顺序

1.public void configConstant(Constants me) 常量配置方法,一般 在里面 读取 配置文件 2.public void configRoute(Routes me) 配置路由,如下 me.add("/", IndexController.class, "/index"); // 第三个参数为该Controller的视图存放路径 me.add("/blog", BlogController.class); //