作者:zhanhailiang 日期:2013-02-01
本节要讨论Nginx如何为一个请求选择匹配的location进行处理。
如下配置文件:
server { listen 80 default_server; server_name itravel.smartcom.cc itravel-beta.huawei.com; client_max_body_size 8M; server_tokens off; root /data/web/itravel2.smartcom.cc/trunk/htdocs; error_page 404 /404.htm; error_page 500 502 503 504 /50x.htm; location / { #root /data/web/itravel2.smartcom.cc/trunk/htdocs; index index.php index.html index.htm; if (!-e $request_filename) { rewrite ^(.+)\.html$ $1.php last; } } location /static/js/ { #root /data/web/itravel2.smartcom.cc/trunk/htdocs; concat on; concat_types text/javascript; } location /static/css/ { #root /data/web/itravel2.smartcom.cc/trunk/htdocs; concat on; concat_types text/css; } location /api { } location ~/\.ht { } location ~ ^/~([^/]+)(/?.*)$ { } location ~ \.do$ { } location ~ \.(jpg|jpeg|gif|png|ico|css|tgz|gz|bz2|pdf|txt|tar|bmp|js|mov) { } location ~ /trip/ { } location /trip/ { } location ~ \.php$ { } }
第一步:请求URI(路径)规范化。
所谓规范化,就是先将URI中形如“%XX”的编码字符进行解码,再解析URI中的相对路径“.”和“..”部分, 另外还可能会压缩相邻的两个或多个斜线成为一个斜线。
举例说明:若REQUEST_URI为//trip/t.php,则规范化后为/trip/t.php,Nginx将规范前的值存放在$request_uri中,而规范化后的值存放在$uri中。
其中,$request_uri和$uri为Nginx内嵌变量。
第二步:请求URI路径匹配。
首先需要明确Nginx中将路径匹配分为两类:
-
前缀路径匹配 ,即前缀字符串定义的路径,如上配置文件中“/,/static/js/,/static/css/,/api,/trip/”
-
正则表达式路径匹配 ,即使用正则表达式需要在路径开始添加“~*”前缀 (不区分大小写),或者“~”前缀(区分大小写)。如上配置文件中“/\.ht,^/~([^/]+)(/?.*)$,\.do$,/trip/,\.php$,\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar||bmp|rtf|js|mov)”
其次为了根据请求URI查找路径,需要明确路径匹配的顺序:
Nginx首先检查前缀字符串定义的路径 (前缀路径),在这些路径中找到能最精确匹配请求URI的路径。然后Nginx按在配置文件中的出现顺序检查正则表达式路径,匹配上某个路径后即停止匹配并使用该路径的配置,否则使用最大前缀匹配的路径的配置。
举例说明:请求/trip/t.php,首先进行前缀路径匹配,最精确的前缀路径为/trip/,接下来进行正则表达式匹配,匹配到\.php$,从而进行location ~ \.php$ { }处理请求。反之若请求的是/trip/t.html,由于没有正则表达式匹配到该URI,故匹配最精确的前缀路径匹配,即进入location /trip/ { }处理请求。若想不论是请求/trip/t.php,还是/trip/t.html,都匹配到/trip/进行处理,则可以使用location ^~ /trip/ { },这样Nginx就不会再检查正则表达式了。
备注:
路径可以嵌套,但有例外。
在不区分大小写的操作系统(诸如Mac OS X和Cygwin)上,前缀匹配忽略大小写(0.7.7)。但是,比较仅限于单字节的编码区域(one-byte locale)。
正则表达式中可以包含匹配组(0.7.40),结果可以被后面的其他指令使用。
如果最大前缀匹配的路径以“^~”开始,那么Nginx不再检查正则表达式。在0.7.1到0.8.41的所有Nginx中,如果请求匹配的前缀字符串路径并没有“=”或“^~”前缀, 路径查找过程仍然会停止,而不进行正则表达式匹配。而且,使用“=”前缀可以定义URI和路径的精确匹配。如果发现匹配,则终止路径查找。 比如,如果请求“/”出现频繁,定义“location = /”可以提高这些请求的处理速度, 因为查找过程在第一次比较以后即结束。这样的路径明显不可能包含嵌套路径。