当前位置: 代码迷 >> Web前端 >> Nginx途径匹配规则详解
  详细解决方案

Nginx途径匹配规则详解

热度:386   发布时间:2013-02-17 10:44:46.0
Nginx路径匹配规则详解
  作者: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中将路径匹配分为两类:

  1. 前缀路径匹配,即前缀字符串定义的路径,如上配置文件中“/,/static/js/,/static/css/,/api,/trip/”
  2. 正则表达式路径匹配,即使用正则表达式需要在路径开始添加“~*”前缀 (不区分大小写),或者“~”前缀(区分大小写)。如上配置文件中“/\.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 = /”可以提高这些请求的处理速度, 因为查找过程在第一次比较以后即结束。这样的路径明显不可能包含嵌套路径。

扩展阅读:

  • location(Tengine)
  • 一个简单PHP站点配置
  • 内嵌变量