zoukankan      html  css  js  c++  java
  • [转载+整理]Nginx Location匹配规则

    规则语法

    语法 匹配规则
    普通匹配(遵循最大前缀匹配规则, 优先度比正则低)
    = 精确(严格)匹配, 优先度最高
    后续不再匹配正则
    ^~ 非正则匹配(依然遵循最大前缀匹配规则)
    后续不再匹配正则
    ~ 表示区分大小写的正则匹配
    ~* 表示不区分大小写的正则匹配
    / 通用匹配,任何请求都会匹配到(本质上等同于语法 )

    !~!~* 分别为区分大小写不匹配及不区分大小写不匹配 的正则, 但是是用于条件判断的时候(即 if 语句)

    if ($host !~* "^www.") {
        # ...
    }
    

    匹配简单来说:

    1. 优先匹配 = 精确匹配, 若未匹配到则转下一步骤

    2. 依照最大前缀匹配规则, 先匹配普通规则( , ^~)

      若最终匹配到 ^~, 则使用

      若匹配到 或 未匹配到, 则转下一步骤(当前匹配结果暂时保存)

    3. 按照物理存储顺序, 若匹配到任意一条正则, 马上使用(无视后面正则)

      若未匹配到任意正则, 则使用步骤2中匹配到普通正则

    location 分类

    只有两类:正则location和普通location

    ~~* 为正则location
    =^~@和无任何前缀的都属于普通location,另外,@是用作服务端内部的一种转发行为,很少用,在此不做讨论。

    匹配顺序:

    1. 先普通,再正则
    2. 普通location之间的匹配顺序:按最大前缀匹配
      location /a/{}location /a/b/ {},请求 http://a/b/c.html 匹配的是 location /a/b/ {}
    3. 正则location之间的匹配顺序:按配置文件中的物理顺序匹配,只要匹配到一条正则,就不再考虑后面的
    4. 若普通location匹配到 精确匹配= 或 非正则匹配 ^~, 则不再进行后续的正则匹配
    5. 普通location与正则location之间的匹配结果选择
      1. 普通location先匹配,匹配到了结果,只是一个临时结果;
      2. 会继续正则location的匹配,
        1. 如果匹配到正则,则用匹配到的正则结果;
        2. 如果没有匹配到正则,则继续用普通匹配的那个结果

    综上,常规的顺序是匹配完普通location,还要继续匹配正则location,但是,也可以告诉nginx,匹配到了普通location,就不要再搜索匹配正则location了,通过在普通location前面加上^~符号,^表示非,~表示正则,^~就是表示不要继续匹配正则。

    除了^~=也可阻止nginx继续匹配正则,区别在于^~依然遵循最大前缀匹配规则,而=是严格匹配

    扩展

    location / {}location =/ {}的区别

    / {}作为普通匹配,是遵循最大前缀匹配原则的,所以,对于一个url,如果有更特殊合适的匹配,就选特殊合适的,如果没有更特殊合适的匹配,也有 / {}兜着,就像是默认配置一样

    =/ {} 遵循的是严格匹配规则,只能匹配到 http://ip:port/,同时会停止搜索正则匹配。

    测试

    接下来测试验证。

    1.先验证第二条:普通location之间的匹配顺序:按最大前缀匹配

    nginx.conf配置:

        #普通location
        location  /a/b {
            return 666;
        }
        #普通location
        location /a/b/c {
            return 777;
        }
    

    测试链接:http://192.168.88.38/a/b,http状态码为666,符合预期。如图(后面的测试可自行F12打开浏览器控制台查看http状态码,不再截图):

    测试链接:http://192.168.88.38/a/b/c,http状态码为777,匹配的是location /a/b/c {return 777;},符合预期。

    2.验证第三条:正则location之间的匹配顺序:按配置文件中的物理顺序匹配,只要匹配到一条正则,就不再考虑后面的

    nginx.conf配置:

       location ~* /a {
            return 999;
        }
       #匹配a-z的任意一个字母
       location ~* ^/[a-z]$ {
            return 666;
        }
    

    测试链接:http://192.168.88.38/a,http状态码999,匹配的是location ~* /a {renturn 999;},符合预期。
    将nginx.conf中的两个正则匹配顺序调换下:

        location ~* ^/[a-z]$ {
            return 666;
        }
    
        location ~* /a {
            return 999;
        }
    

    测试链接:http://192.168.88.38/a,http状态码666,匹配的是location ~* ^/[a-z]$,符合预期。

    3.验证第4条,其实第4条就相当于是总结性的匹配顺序了:

    nginx.conf配置:

    #普通location
    location /a {
         return 666;
    }
     #普通location
    location  /a/b {
         return 777;
    }
    #正则location 
    location ~* /a/b { 
         return 888;
    }
    

    测试链接:http://192.168.88.38/a,http状态码666,匹配到普通location,location /a {return 666;},符合预期。
    测试链接:http://192.168.88.38/a/b,http状态码777,先进行普通location匹配,遵循最大前缀原则,匹配到location /a/b {return 777; },但是,这只是一个临时结果,因为接下来还要继续往下进行正则location匹配,匹配到 location ~* /a/b { return 888; },最终返回结果为888。符合预期。
    将正则location的规则改下:

            #普通location
            location /a {
                return 666;
            }
            #普通location
            location  /a/b {
                return 777;
            }
            #正则location
            location ~* /a/c {
                return 888;
             }
    

    测试链接:http://192.168.88.38/a/b,http状态码777,匹配到location /a/b {return 777; },并且因为接下来没有符合的正则location,所以最终返回为777,符合预期。

    综上,location的匹配顺序及结果取值都符合2,3,4点结论。
    接下来再测试验证普通location中的~及=符号对于匹配搜索过程的阻断效果,当然,别忘了这俩符号的真实作用。~为普通字符匹配,=为精确匹配。
    ^~测试验证nginx.conf配置:

         location /a {
            return 666;
        }
        #普通匹配
        location ^~ /a/b {
            return 777;
        }
        #正则location
        location ~* /a/b {
            return 888;
        }
    

    测试链接:http://192.168.88.38/a/b,匹配到 location ^~ /a/b {return 777;}后,因为使用了^~符号,不再继续搜索正则location匹配,所以,虽然下面有符合条件的正则location,但是最终还是返回了777,符合预期。
    =测试验证nginx.conf配置:

        location /a {
            return 666;
        }
        #普通匹配
        location = /a/b {
            return 777;
        }
        #正则location
        location ~* /a/b {
            return 888;
        }
    

    测试链接:http://192.168.88.38/a/b,匹配到 location = /a/b {return 777;}后,因为使用了=符号,不再继续搜索正则location匹配,最终返回777,符合预期。

    另附上常用正则表达式:

    • . : 匹配除换行符外的任意字符
    • ? : 重复0次或1次
    • : 重复1次或更多次
    • : 重复0次或更多次
    • d :匹配数字
    • ^ : 匹配字符串的开始
    • $ : 匹配字符串的结束
    • {n} : 重复n次
    • {n,} : 重复n次或更多次
    • [c] : 匹配单个字符,如此处的字符 c
    • [a-z] : 匹配a-z小写字母的任意一个
    • (a|b|c):匹配a或b或c

    作者:Etyero
    来源:CSDN
    原文:https://blog.csdn.net/u010798968/article/details/76215445
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    mysql存储过程
    Mysql中的触发器
    快速开始、环境搭建、修改包名、新建模块、正式部署
    windows下redis下载安装
    Windows10下mysql 8.0.19 安装配置方法图文教程
    IDEA中安装SVN
    常见页面报错
    Python AttributeError: 'Module' object has no attribute 'STARTF_USESHOWINDOW'
    如何编写一篇高质量的技术博文?学习本文的排名靠前大法
    Linux use apktool problem包体变大GLIBC2.14等问题
  • 原文地址:https://www.cnblogs.com/youjiaxing/p/10439240.html
Copyright © 2011-2022 走看看