nginx 中 index 指令要注意的事项
最近在做一个nginx配置的时候,遇到个问题,请大家先看第一个配置:
server { listen 80; server_name www.mos.com; access_log logs/mos.log; error_log logs/mos_error.log debug; root /home/web/www; index index.php; location = /index.php { ...... } }
当访问 www.mos.com 时,和预想的一样,会实际执行 /home/web/www 下面的 index.php。
下面再来看第二个配置:
server { listen 80; server_name www.abc.com; index index.html index.php; location / { root /home/web/abc/php/; } location = /index.html { root /home/web/abc/html/; } }
其中:
- /home/web/abc/php 下存在 index.php。
- /home/web/abc/html 下存在 index.html。
这次,当访问 www.abc.com 时,我以前本以为会执行 index.html,但实际执行到的却是 index.php。
自己的误解
请求进入哪一个 location,是根据 request_uri 决定的。由于第一个配置和自己的预期相符,所以我主观的认为 index 指令配置的值,会附加到初始的 request_uri 后面,再去寻找 location。
以第一个例子来说,请求 www.mos.com,实际在寻找 location 时,会用 /index.php 去找。但是如果是这样的话,第二个例子在请求 www.abc.com 时,应该会用index.html去找,这样就应该执行 index.html,但结果却不是这样的。
index指令学习
基于上面的现象,我认识到自己对 index 指令的理解存在问题,所以决定打开手册好好学习一下。
恍然大悟,总结下 index 指令会做的事情如下:
- 这是一个 content 阶段的指令。
- 仅处理 request_uri 结尾为 / 的请求。
请求处理逻辑如下:
- 首先对 index 指令配置的多个文件做顺序查找,看文件是否存在。
- 如果存在,就结束查找过程,把这个文件附加到请求的 request_uri 后面,并且发起一个内部的 redirect。
- 如果全部尝试后都不存在,那么该index指令执行结束,nginx 会继续执行 content 阶段下一个指令的事情。
伪代码如下:
find = false; for(file in file_list) { if(file_exists(file)) { find = true; request_uri = request_uri + file; break; } } if(find) { redirect(request_uri); }
重新分析请求
为了印证对 index 指令的理解,我重新编译 nginx,并将 error_log 级别设置为 debug,分析 www.mos.com 请求,输出如下:
2014/07/30 17:41:11 [debug] 31021#0: *1096 rewrite phase: 0 2014/07/30 17:41:11 [debug] 31021#0: *1096 test location: "/index.php" 2014/07/30 17:41:11 [debug] 31021#0: *1096 using configuration "" ...... 2014/07/30 17:41:11 [debug] 31021#0: *1096 content phase: 9 2014/07/30 17:41:11 [debug] 31021#0: *1096 open index "/home/web/www/index.php" 2014/07/30 17:41:11 [debug] 31021#0: *1096 internal redirect: "/index.php?" 2014/07/30 17:41:11 [debug] 31021#0: *1096 rewrite phase: 0 2014/07/30 17:41:11 [debug] 31021#0: *1096 test location: "/index.php" 2014/07/30 17:41:11 [debug] 31021#0: *1096 using configuration "=/index.php"
在请求 www.mos.com 时,第一次并没有进入到现有的 location 中,之后在 content 阶段执行 index 指令,查找到配置的 index.php 文件存在后,把 request_uri 改为 /index.php 再发起 redirect,最终进入到 location = /index.php{} 中。
有兴趣的话,大家可以自行分析我第二个配置中 www.abc.com 请求会如何做。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论