少用 if … rewrite,多用 try_files

前段时间配置 Nginx 时候碰到了一个问题:Nginx 模块内部暴露出来的资源无法访问。具体来说就是比如某个模块导出了一个资源(比如 /channels-stats)提供统计信息,如下:

location /channels-stats {
# activate channels statistics mode for this location
push_stream_channels_statistics;

# query string based channel id
push_stream_channels_path $arg_id;
}

而在配置文件中还有一下配置,如果访问的文件不存在,则重定向到使用 index.php 去进行访问

if (!-e $request_filename) {
rewrite ^/(.*)$ /index.php/?s=$1 last;
break;
}

这个时候,/channels-stats 是无法被访问到的,原因应该是 /channels-stats 这样的有模块导出的资源并不属于 $request_filename 这个变量的范畴。导致实际访问的其实是 /index.php/?s=channels-stats 。

这个时候也不能用 $request_uri, $uri 等变量去替换 $request_filename 的位置,因为 if 能测试的就只是文件是否存在而已。

想了想,发现这段时间都忘了 Nginx 的 try_files 指令了,以及 if is evil 这条 Nginx 金句了,用下面这条可以替代上面的,并且可以保证  /channels-stats 仍然可以访问

try_files $uri $uri/ /index.php?s=$request_uri;

这里讲了不该用 if 的:
http://wiki.nginx.org/Pitfalls#Check_IF_File_Exists
http://wiki.nginx.org/IfIsEvil
更新:这里的问题其实是把”if (!-e $request_filename)”测试放到 location / 下面就很好解决了的,不知道当时为什么脑子短路了,没有发现。。。