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 状态码的。
Nginx 配置指令的执行顺序(十一)的更多相关文章
- Nginx 配置指令的执行顺序(八)
前面我们详细讨论了 rewrite.access 和 content 这三个最为常见的 Nginx 请求处理阶段,在此过程中,也顺便介绍了运行在这三个阶段的众多 Nginx 模块及其配置指令.同时可以 ...
- Nginx 配置指令的执行顺序(五)
Nginx 的 content 阶段是所有请求处理阶段中最为重要的一个,因为运行在这个阶段的配置指令一般都肩负着生成“内容”(content)并输出 HTTP 响应的使命.正因为其重要性,这个阶段的配 ...
- Nginx 配置指令的执行顺序(一)
大多数 Nginx 新手都会频繁遇到这样一个困惑,那就是当同一个 location 配置块使用了多个 Nginx 模块的配置指令时,这些指令的执行顺序很可能会跟它们的书写顺序大相径庭.于是许多人选择了 ...
- Nginx配置指令的执行顺序
rewrite阶段 rewrite阶段是一个比较早的请求处理阶段,这个阶段的配置指令一般用来对当前请求进行各种修改(比如对URI和URL参数进行改写),或者创建并初始化一系列后续处理阶段可能需要的Ng ...
- Nginx 配置指令的执行顺序(十)
运行在 post-rewrite 阶段之后的是所谓的 preaccess 阶段.该阶段在 access 阶段之前执行,故名preaccess. 标准模块 ngx_limit_req 和 ngx_lim ...
- Nginx 配置指令的执行顺序(六)
前面我们在 (五) 中提到,在一个 location 中使用 content 阶段指令时,通常情况下就是对应的 Nginx 模块注册该 location 中的“内容处理程序”.那么当一个 locati ...
- Nginx 配置指令的执行顺序(三)
如前文所述,除非像 ngx_set_misc 模块那样使用特殊技术,其他模块的配置指令即使是在 rewrite 阶段运行,也不能和 ngx_rewrite 模块的指令混合使用.不妨来看几个这样的例子. ...
- Nginx 配置指令的执行顺序(二)
我们前面已经知道,当 set 指令用在 location 配置块中时,都是在当前请求的 rewrite 阶段运行的.事实上,在此上下文中,ngx_rewrite 模块中的几乎全部指令,都运行在 rew ...
- Nginx 配置指令的执行顺序
在一个 location 中使用 content 阶段指令时,通常情况下就是对应的 Nginx 模块注册该 location 中的“内容处理程序”.那么当一个 location 中未使用任何 cont ...
随机推荐
- 给FPGA初学者的建议——不要浮躁(转)
原作者:http://hi.baidu.com/zhoubin7020 作为FPGA新人常常在论坛上问,用什么语言啊,用什么软件啊,用那个公司的芯片等问题.我个人认为学习FPGA和学习单片机有相同的道 ...
- Ubuntu14.04LST 安装Oracle SQL Developer 4.0.2
1:Oracle SQL Developer 4.0.2下载链接: http://www.oracle.com/technetwork/developer-tools/sql-developer/do ...
- Ext.getCmp()的简单使用
Ext.getCmp(Ext组件ID),根据Ext组件的ID选择EXT组件. 例如:点击Panel->toolbar上的button改变Panel的标题 Ext.onReady(function ...
- Log4net 可直接使用的配置
config配置 <xml version="1.0"> <configuration> <configSections> <!--配置一 ...
- Erlang千万级用户游戏框架(Openpoker)源码文件分析清单
openpoker源码 erlang写的网游服务器源码,OpenPoker是一个大型多人扑克网游,内建支持了容错能力,负载平衡和无限制的规模大小.本文是openpoker源码文件功能的一个清单式说明: ...
- Xcopy参数介绍
DOS批处理命令,永远是不朽的命令,不仅功能强大,同时,速度也是最快的!但是,很多新手学习计算机,都已经遗忘了本不该忘记的批处理命令. 我们不可数典忘祖,该学习的还是要学习,不该忘记的还是不能忘记,尤 ...
- 二十六、Jcreator使用初步
摘自http://blog.csdn.net/liujun13579/article/details/7751464 二十六.Jcreator使用初步 Jcreator是一个小巧灵活的Java开发工具 ...
- java连接oracle数据库详细代码
详细代码: import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;imp ...
- Unity 调用android插件
1. Unity的Bundle Identifier必须和你的android报名一致 Activity和View的区别: Activity应该是一个展示页面,View是页面上一些按钮视图等等. 如何调 ...
- 解决在Linux下安装Oracle时的中文乱码问题
本帖最后由 TsengYia 于 2012-2-22 17:06 编辑 解决在Linux下安装Oracle时的中文乱码问题 操作系统:Red Hat Enterprise Linux 6.1数据库:O ...