1.location拦截规则

原文链接:
Nginx的server中往往有多个location共存,每个location定义自己的匹配规则和proxy信息,对于每一个请求,需要有一定的优先级来找到自己合适的location。
locaiton有四种类型的匹配规则,分别为

  • 完全匹配(=)
  • 无正则普通匹配(^~)(^ 表示“非”,~ 表示“正则”,字符意思是:不要继续匹配正则)
  • 正则表达式匹配(~或者~*)
  • 普通匹配(/xxx)

    1.1规则

  • 等号类型(=)的优先级最高。一旦匹配成功,则不再查找其他location的匹配项

  • 剩下的几种匹配优先级略复杂,具体可以参考Nginx文档(http://nginx.org/en/docs/http/ngx_http_core_module.html#location
    • ^~和普通匹配。使用前缀匹配,不支持正则表达式,如果有多个location匹配成功的话,不会终止匹配过程,会记忆表达式最长的那个
    • 如果上一步得到的最长的location为^~类型,则表示阻断正则表达式,不再匹配正则表达式
    • 如果上一步得到的最长的location不是^~类型,继续匹配正则表达式,只要有一个正则成功,则使用这个正则的location,立即返回结果,并结束解析过程

      1.2“最长”命中

      ^~和普通命中,都是优先使用匹配最长的结果,示例如下:
      1. location ^~ /a {
      2. root /;
      3. }
      4. location ^~ /aaa {
      5. root /aaa;
      6. }
      如果url为/aaa,则上面两个location都匹配成功,但用于location ^~ /aaa较长,所以最终会以/aaa作为root
      上例中如果是普通匹配(把location的^~去掉),结果也是一样的

      示例 ```
  1. location /test_1 {
  2. return 400;
  3. }
  4. location ^~ /test {
  5. return 401;
  6. }
    1. 如上如果path为/test_1,返回的是400,说明^~优先级并不比普通匹配高<br />
  7. location /test_1 {
  8. return 400;
  9. }
  10. location ^~ /test {
  11. return 401;
  12. }
  13. location ~ /test {
  14. return 402;
  15. }
    1. 如上如果path为/test_1,返回的是402,此时^~和普通匹配只记住了最长一个location /test_1,不会阻止正则<br />如果path为/test,返回401,此时^~和普通匹配只记住了最长一个location ^~ /test,会阻止正则<br /> 1.2路径替换<br />**规则**<br />配置proxy_pass时,可以实现URL路径的部分替换。<br />proxy_pass的目标地址,默认不带/,表示只代理域名,urlquerystring部分不会变(把请求的path拼接到proxy_pass目标域名之后作为代理的URL)<br />如果在目标地址后增加/,则表示把pathlocation匹配成功的部分剪切掉之后再拼接到proxy_pass目标地址<br />比如请求 /a/b.html
    location /a { proxy_pass http://server; }
    1. ```
    2. location /a/ {
    3. proxy_pass http://server/;
    4. }
    如上两个匹配成功后,实际代理的目标url分别是
    http://server/a/b.html (把/a/b.html拼接到http://server之后)
    http://server/b.html (把/a/b.html的/a/去掉之后,拼接到http://server/之后)
    要求
    注意的是,对于location为正则表达式的匹配,proxy_pass的目标地址不可以带/
    比如,如下配置会报错:
    1. location ~ /abc(.*) {
    2. proxy_pass http://127.0.0.1/x;
    3. }
    正则表达式的替换
    如果是正则表达式,想要实现proxy_pass的路径替换,可以使用如下方式: ```
  16. location ~ /abc(.*) { # 注意,使用这种方式,location内部不能包含if语句,否则proxy_pass不会生效
  17. proxy_pass http://127.0.0.1/x$1;
  18. }
    1. 如上可以把(.*)所匹配的内容拼接到[http://127.0.0.1/x](http://127.0.0.1/x) 之后,关于$1的使用,可以参考各种编程语言的正则表达式<br />另一种方法是:
  19. location /abc { # 这里也可以是正则
  20. proxy_pass http://127.0.0.1/x$request_uri; 3.
    1. <a name="CoMr6"></a>
    2. ### 1.3老师总结
    location匹配顺序 在没有标识符的请求下,匹配规则如下: 1、nginx服务器首先在server块的多个location块中搜索是否有标准的uri和请求字符串匹配。如果有多个标准uri可以匹配,就匹配其中匹配度最高的一个location。 2、然后,nginx在使用location块中,正则uri和请求字符串,进行匹配。如果正则匹配成功,则结束匹配,并使用这个location处理请求;如果正则匹配失败,则使用标准uri中,匹配度最高的location。 备注: 1、如果有精确匹配,会先进行精确匹配,匹配成功,立刻返回结果。 2、普通匹配与顺序无关,因为按照匹配的长短来取匹配结果。 3、正则匹配与顺序有关,因为是从上往下匹配。(首先匹配,就结束解析过程) 4、在location中,有一种统配的location,所有的请求,都可以匹配,如下: location / {

    因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求

    但是正则和最长字符串会优先匹配

    }
    结合标识符,匹配顺序如下: (location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (location /) 即 (精确匹配)> (最长字符串匹配,但完全匹配) >(非正则匹配)>(正则匹配)>(最长字符串匹配,不完全匹配)>(location通配)
  1. **请求的路径匹配location,可以比location长,但绝对不能段。112.74.110.26/schoolmanager可以匹配location /school{},但是匹配不上location /schoolmanagerkkk{}**
  2. <a name="G0lsI"></a>
  3. ## 2.loaction、ip、网址之间的关系
  4. 一个ip地址可以对应多个网址,但是一个网址只能对应一个ip地址。location既可以根据ip来拦截,也可以根据网址来拦截。假如chuxin1.com chuxin2.com都对应112.74.110.26网址我们配置两个server,那么chuxin1.com/ace-master访问的是static1下的index.htmlchuxin2.com/ace-master访问的是static2下的index.html。这说明dns域名解析解析除了ip地,找到了相应的服务器,但是我们请求过去的其实是chuxin.com的网址。

server { listen 80; server_name chuxin1.com; location /ace-master { root /opt/static; index index.html index.htm; } }

server { listen 80; server_name 2; location /ace-master { root /opt/static2; index index.html index.htm; } } ```