nginx location匹配顺序

先查阅资料

很多网页都有说明。一遍没有看懂,还是找官网,比较权威。
http://nginx.org/en/docs/http/ngx_http_core_module.html#location
一下是根据网站的意思整理成初步顺序。

regular expression – Regular expressions are specified with the preceding “~*” modifier (for case-insensitive matching), or the “~” modifier (for case-sensitive matching)

  1. first checks locations defined using the prefix strings;
  2. location with the longest matching prefix is selected and remembered;
  3. If the longest matching prefix location has the “^~” modifier then
    regular expressions are not checked.
  4. regular expressions are checked
  5. in the order of their appearance in the configuration file;
  6. The search of regular expressions terminates on the first match
  7. If no match with a regular expression is found then the
    configuration of the prefix location remembered earlier is used

只看到正则表达是 ~ ~*,也没有搞懂prefix string是什么意思。

我们一起来看看nginx plus的介绍:
There are two types of parameter to the location directive: prefix strings (pathnames) and regular expressions

  1. Test the URI against all prefix strings.
  2. The = (equals sign) modifier defines an exact match of the URI and a
    prefix string. If the exact match is found, the search stops.
  3. If the ^~ (caret-tilde) modifier prepends the longest matching
    prefix string, the regular expressions are not checked.
  4. Store the longest matching prefix string.
  5. Test the URI against regular expressions(~ or ~*).
  6. Stop processing when the first matching regular expression is found
    and use the corresponding location.
  7. If no regular expression matches, use the location corresponding to
    the stored prefix string.

nginx plus 第4条和 nginx http module中的第2条意思一样。

按照语法,这四个表达式可以省略。
location [ = | ~ | ~* | ^~ ] uri { … }

猜测prefix strings (pathnames),应该是直接使用uri,省略语法中四个表达式。

在网站中测试下

https://detailyang.github.io/nginx-location-match-visible/

location /a {}
location = /a {}
location ^~ /a {}
location ~* /A {}
location ~ /a {}
location /abc {}
访问/ab 匹配到 ^~ /a
访问/abc 还是匹配到 ^~ /a 根据第三条

删掉 ^~ /a,变成:
location /a {}
location = /a {}
location ~* /A {}
location ~ /a {}
location /abc {}
访问 /abc ,匹配到 ~ /a 根据第五条

删掉 ~ /a,变成:
location /a {}
location = /a {}
location ~* /A {}
location /abc {}
访问 /abc 匹配到 /abc ,,,不知道为什么没有匹配~* /A,一会测试下。

找台机器测试下

server {
    listen 192.168.200.241:80;
    server_name www.a.com;
    location /a { return 200 "matched /a\n"; }
    location = /a { return 200 "matched = /a\n"; }
    location ^~ /ab { return 200 "matched ^~ /ab\n"; }
    location ~* /a { return 200 "matched ~* /a\n"; }
    location ~ /a { return 200 "matched ~ /a\n"; }
    location /abc { return 200 "matched /abc\n"; }  
}

star@STAR-LEE:~$ curl http://192.168.200.241/abc
matched ~* /a
star@STAR-LEE:~$ curl http://192.168.200.241/Abc
matched ~* /a
貌似那个网站有些内容不是很准确。
接下来继续测试:
把~* /a移动到~ /a后面

server {
    listen 192.168.200.241:80;
    server_name www.a.com;
    location /a { return 200 "matched /a\n"; }
    location = /a { return 200 "matched = /a\n"; }
    location ^~ /ab { return 200 "matched ^~ /ab\n"; }
    location ~ /a { return 200 "matched ~ /a\n"; }
    location ~* /a { return 200 "matched ~* /a\n"; }
    location /abc { return 200 "matched /abc\n"; }  
}

节约下篇幅。。。

star@STAR-LEE:~$ curl http://192.168.200.241/Abc
matched ~* /a
star@STAR-LEE:~$ curl http://192.168.200.241/abc
matched ~ /a
说明 ~ 和 ~* 优先级相等。

突发奇想,在= ,prefix string,^~后面使用perl正则表达式会怎么样。

server {
    listen 192.168.200.241:80;
    server_name www.a.com;
    location /a { return 200 "matched /a\n"; }
    location = /a { return 200 "matched = /a\n"; }
    location ^~ /ab* { return 200 "matched ^~ /ab\n"; }
    location ~* /a { return 200 "matched ~* /a\n"; }
    location ~ /a { return 200 "matched ~ /a\n"; }
    location /abc { return 200 "matched /abc\n"; }  
}

star@STAR-LEE:~$ curl http://192.168.200.241/abc
matched ~* /a
star@STAR-LEE:~$ curl http://192.168.200.241/ab*
matched ^~ /ab

貌似不是按照正则表达式来的。说明:
只有在~,~*后面可以使用perl的正则表达式。
prefix string , = , ^~ 后面跟正则表达式都无效。

总结下

这样匹配顺序就理清楚了:
1.首先用prefix strings走一遍,记录最长匹配;
2.如果被 = 精确匹配,则不再查找;
3.如果 ^~ 匹配的是prefix strings中最长匹配,则不使用正则表达式查找;
4.使用 ~ 或 ~* 匹配到第一个,则不再查找;
5.如果4没有匹配到,使用1中记录的最长匹配;

来验证一下:
先不使用正则表达式

server {
    listen 192.168.200.241:80;
    server_name www.a.com;
    location /a { return 200 "matched /a\n"; }
    location = /a { return 200 "matched = /a\n"; }
    location ^~ /ab { return 200 "matched ^~ /ab\n"; }
    # location ~* /a { return 200 "matched ~* /a\n"; }
    # location ~ /a { return 200 "matched ~ /a\n"; }
    location /abc { return 200 "matched /abc\n"; }  
}

star@STAR-LEE:~$ curl http://192.168.200.241/a
matched = /a
star@STAR-LEE:~$ curl http://192.168.200.241/ab
matched ^~ /ab
star@STAR-LEE:~$ curl http://192.168.200.241/abc
matched /abc
star@STAR-LEE:~$ curl http://192.168.200.241/abcd
matched /abc
star@STAR-LEE:~$ curl http://192.168.200.241/abd
matched ^~ /ab

测试下正则表达式的影响:

server {
    listen 192.168.200.241:80;
    server_name www.a.com;
    location /a { return 200 "matched /a\n"; }
    location = /a { return 200 "matched = /a\n"; }
    location ~* /a { return 200 "matched ~* /a\n"; }
    location ~ /a { return 200 "matched ~ /a\n"; }
    location ^~ /ab { return 200 "matched ^~ /ab\n"; }
    location /abc { return 200 "matched /abc\n"; }  
}

star@STAR-LEE:~$ curl http://192.168.200.241/abc
matched ~* /a
location /abc虽然是prefix string中的最长匹配,使用顺序4;

star@STAR-LEE:~$ curl http://192.168.200.241/abcd
matched ~* /a
location /abc虽然是prefix string中的最长匹配,使用顺序4;

star@STAR-LEE:~$ curl http://192.168.200.241/abd
matched ^~ /ab
使用顺序3,并且不受位置影响,即使在正则表达式后面也无所谓。

想起nginx plus location中的一句话:
For a request URI to match a prefix string, it must start with the prefix string.
不知何意,如有好心人知道,还请指点迷经。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值