先查阅资料
很多网页都有说明。一遍没有看懂,还是找官网,比较权威。 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. 不知何意,如有好心人知道,还请指点迷经。
|