Nginx localhost路由匹配规则

URI 即统一标识资源符,通用的 URI 语法格式如下:

scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]

格式说明如下:

  • 在 Nginx 的应用场景中,URL 与 URI 并无明确区别。URI 标准(RFC3986)中约定,URL 是 URI 的一个子集;
  • scheme 是 URI 请求时遵守的协议,常见的有 HTTP、HTTPS、FTP;
  • host[:port] 是主机名与端口号,HTTP 协议的默认端口是 80,HTTPS 协议的默认端口是 443;
  • [/path] 是访问路径与访问文件名;
  • [?query] 是访问参数,访问参数以“?”开始作标识,由多个以“&”连接的 key=value 形式的字符串组成。

语法

location [= | ~ | ~* | ^~ | @] URI

位置

server,location

其中,[=||*|^~|@]部分称为 location 修饰语(Modifier),修饰语定义了与 URI 的匹配方式。URI 为匹配项,可以是字符串或正则表达式。

URI 匹配规则

uri变量是待匹配的请求字符串,可以不包含正则表达式,也可以包含正则表达式,那么nginx服务器在搜索匹配location的时候,是先使用不包含正则表达式进行匹配,找到一个匹配度最高的一个,然后在通过包含正则表达式的进行匹配,如果能匹配到直接访问,匹配不到,就使用刚才匹配度最高的那个location来处理请求。

无修饰语

修饰符

解释

location 后没有参数直接跟着 标准 URI,表示前缀匹配,代表跟请求中的 URI 从头开始匹配。

server {
    location /abc {
      ...
    }
}

以下访问:只要以前缀abc开始就可以匹配,?后的都是访问参数

http://192.168.204.131/abc/def
http://192.168.204.131/abc?p1=TOM
http://192.168.204.131/abc/
http://192.168.204.131/abcdef...

修饰语 "="

修饰符

=

解释

用于标准 URI 前,要求请求字符串与其精准匹配,成功则立即处理,nginx停止搜索其他匹配,Linux 系统下会区分大小写,Windows 系统下则不会

server {
    location =/abc {
      ...
    }
}

以下访问:只能完全匹配 abc; ?后的都是访问参数

#可以匹配
http://192.168.204.131/abc
http://192.168.204.131/abc?p1=TOM
#匹配不到
http://192.168.204.131/abc/
http://192.168.204.131/abcdef
http://192.168.204.131/abc/def

修饰语 "~ | ~*"

修饰符

~ | ~*

解释

用于正则 URI 前,表示 URI 包含正则表达式,~ 区分大小写,~* 不区分大小写

server {
        location ~ ^/ABCD$ {
          ... 
        }
    }

server {
        location ~* ^/abcd$ {
          ... 
        }
    }

以下访问:

# ~ 匹配
http://192.168.204.131/ABCD
http://192.168.204.131/ABCD?name=tom
# ~ 不匹配
http://192.168.204.131/ABCD/
# ~* 匹配
http://192.168.204.131/aBcD
http://192.168.204.131/abcd?p1=TOM
# ~* 不匹配
http://192.168.204.131/abcd/

修饰语 "^~"

修饰符

^~

解释

用于标准 URI 前,并要求一旦匹配到就会立即处理,不再去匹配其他的那些个正则 URI,一般用来匹配目录;注意,这不是一个正则表达式匹配,它的目的是优先于正则表达式的匹配

server {
    location ^~ /abc {
      ...
    }
}

修饰语 "@"

修饰符

@

解释

@ 定义一个命名的 location,@ 定义的locaiton名字一般用在内部定向,例如error_page, try_files命令中。它的功能类似于编程中的goto。

server {
    location @jump_to_error_page {
       default_type text/plain;
       return 200 "not found ";
    }
     
    error_page 404 =200 @jump_to_error_page;
}

表示没找页面或资源,但是我正确返回了200,并通知没找到。

匹配顺序

优先级

修饰符

解释

1

location =

# 精准匹配

2

location ^~

# 带参前缀匹配

3

location ~

# 正则匹配(区分大小写)

4

location ~*

# 正则匹配(不区分大小写)

5

location /a

# 普通前缀匹配,优先级低于带参数前缀匹配

6

location /

# 任何没有匹配成功的,都会匹配这里处理

案例分析

案例1

location  /doc {
      return 701;
  }
  
  location ~* ^/document$ {
      return 702;
  }

curl -i localhost/document 702
按照上述的规则,显然第二个正则匹配会有更高的优先级

案例2

location  /document {
      return 701;
  }
  
  location ~* ^/document$ {
      return 702;
  }

curl -i localhost/doucument 702
第二个匹配了正则表达式,优先级高于第一个普通前缀匹配

案例3

location ^~ /doc {
      return 701;
  }

  location ~* /document {
      return 702;
  }

curl -i localhost/document 701
第一个前缀匹配 ^~ 命中以后不会再搜寻正则匹配,所以会第一个命中

案例4

location /docu {
      return 701;
  }

  location /doc {
      return 702;
  }
  
  location /my {
      return 701;
  }

  location /myweb {
      return 702;
  }

curl -i localhost/document 701
curl -i localhost/doc 702
curl -i localhost/myweb 702
curl -i localhost /mywebm 702
前缀匹配下,返回最长匹配的 ,与 location 所在位置顺序无关
curl -i localhost/myw 701
前缀匹配下,字符串没达到最长匹配,返回短的 location;

案例 5

location ~* ^/doc[a-z]+ {      
      return 701;
  }

  location ~* ^/docu[a-z]+ {
      return 702;
  }
  
  location ~* ^/myw[a-z]+ {
     return 701; 
  }

  location ~* ^/my[a-z]+ {
      return 702;
  }

curl -i localhost/document 701
curl -i localhost/myweb 701
可见正则匹配是使用文件中的顺序,先匹配成功的返回。
curl -i localhost/myw 702
当完全匹配,就使用完全匹配 location;

location 实际使用建议

直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理
这里是直接转发给后端应用服务器

location = / {
    proxy_pass http://192.168.204.131:19901/index
}

第二个必选规则是处理静态文件请求,这是 nginx 作为 http 服务器的强项,有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用:

location ^~ /static/ {
    root /html/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js)$ {
    root /html/res/;
}

第三个规则就是通用规则,用来转发动态请求到后端应用服务器,非静态文件请求就默认是动态请求;

location / {
    proxy_pass http://192.168.204.131:19901/
}