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)
- first checks locations defined using the prefix strings;
- location with the longest matching prefix is selected and remembered;
- If the longest matching prefix location has the “^~” modifier then
regular expressions are not checked. - regular expressions are checked
- in the order of their appearance in the configuration file;
- The search of regular expressions terminates on the first match
- 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
- Test the URI against all prefix strings.
- The = (equals sign) modifier defines an exact match of the URI and a
prefix string. If the exact match is found, the search stops. - If the ^~ (caret-tilde) modifier prepends the longest matching
prefix string, the regular expressions are not checked. - Store the longest matching prefix string.
- Test the URI against regular expressions(~ or ~*).
- Stop processing when the first matching regular expression is found
and use the corresponding location. - 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.
不知何意,如有好心人知道,还请指点迷经。