接触Nginx有好几年时间了,一直都是处于会修改配置文件阶段,并且关于location模块还不熟悉,一直都是到处百度谷歌阶段,并且搜索出来博客的说法个个不同,也Nginx官方文档写的也是模棱两可,所以必须抽出两天时间来学习下location模块的匹配规则与优先级,安装方面不过多讲解。
1.匹配模式(与nginx文档叫法不一样,有所差异,但是可以忽略)
# 1.精准匹配
locaiton = /index.html {
root /usr/share/nginx/html1;
index index.html;
}
# 2.1 前缀普通匹配
locaiton ^~ /file {
root /usr/share/nginx/html2;
index index.html;
}
# 2.2 普通匹配
locaiton /file {
root /usr/share/nginx/html2;
index index.html;
}
# 3.1 正则匹配(区分大小写)
locaiton ~ html$ {
root /usr/share/nginx/html3;
index index.html;
}
}
# 3.2 正则匹配(不区分大小写)
location ~* html$ {
root /usr/share/nginx/html3;
index index.html;
}
2.开始比较差异
1.精准匹配
这个不过多解释了,优先级最高,如果命中立马结束解析,例子:
locaiton = /index.html {
root /usr/share/nginx/html1;
index index.html;
}
当前url必须等于/index.html,如:blog.totmp.com/index.html才会命中。
注意:这里有对nginx有点熟悉的朋友就会想,nginx如果只输入host,如blog.totmp.com,nginx会默认转发到nginx编译中'--prefix'参数下的html/index.html,这会不会命中呢?
[root@localhost conf.d]# nginx -V
......
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx
....
查看error.log,答案是:不命中,全部走默认的配置文件。
实际报错是:"/etc/nginx/html/index.html" is not found,证明走了默认配置目录/etc/nginx下。
2.1前缀普通匹配
locaiton ^~ /aa {
root /usr/share/nginx/html1;
index index.html;
}
locaiton ^~ /a {
root /usr/share/nginx/html2;
index index.html;
}
请求的url等于/aaa,按照道理是两个都能匹配上的,好了我们查看请求错误日志。
实际报错是:open() "/usr/share/nginx/html1/aaa" failed. 证明走了aa的配置。
2.2普通匹配()
locaiton /aa {
root /usr/share/nginx/html1;
index index.html;
}
locaiton /a {
root /usr/share/nginx/html2;
index index.html;
}
请求的url等于/aaa,按照道理是两个都能匹配上的,好了我们查看请求错误日志。
实际报错是open() "/usr/share/nginx/html1/aaa" failed,证明走aa的配置与前缀普通匹配一致.
注意:到这里会有小伙伴问了:
问题1: 设置 location = /index.html {} 与 location = /index.html {} 一模一样配置的会怎么样?
问题2: 设置 location /aa {} 与 location /aa {} 一模一样配置的会怎么样?
问题3: 设置 location ^~ /aa {} 与 location ^~ /aa {} 一模一样配置的会怎么样?
问题4: 设置 location /aa {} 与 location ^~ /aa {} 会怎么样?
测试问题4:重启nginx出错不允许这么配置:duplicate location "/aa" in /etc/nginx/conf.d/default.conf:16
归纳:location /aa {} 与 location ^~ /aa {} 普通匹配与前缀普通匹配配置都无法一致,问题123肯定一样报错。
测试后发现猜想正确!
3.1正则匹配(区分大小写),匹配以a结尾与匹配以aa结尾
locaiton ~ a$ {
root /usr/share/nginx/html1;
index index.html;
}
locaiton ~ aa$ {
root /usr/share/nginx/html2;
index index.html;
}
请求的url等于/aaa,按照道理是两个都能匹配上的,好了我们查看请求错误日志。
实际报错是open() "/usr/share/nginx/html1/aaa" failed,为什么是html1目录?
好,我们改下顺序!
locaiton ~ aa$ {
root /usr/share/nginx/html1;
index index.html;
}
locaiton ~ a$ {
root /usr/share/nginx/html2;
index index.html;
}
请求的url等于/aaa,实际报错是open() "/usr/share/nginx/html1/aaa" failed.
这貌似和location配置位置顺序有关?
3.2正则匹配
locaiton ~ a$ {
root /usr/share/nginx/html1;
index index.html;
}
locaiton ~* a$ {
root /usr/share/nginx/html2;
index index.html;
}
其实到这里大家都猜到结果了。
当url等于/a的时候走的html2目录,当url等于/A的时候走的html2目录。
再次提问:设置 location ~ a$ {} 与 location ~ a$ {} 一模一样会怎么样?
设置 location ~* a$ {} 与 location ~* a$ {} 一模一样会怎么样?
设置 location ~ a$ {} 与 location ~* a$ {} 一模一样会怎么样?
测试答案证实:都是正常重启运行。
最后总结下吧:
优先级:
精准 > (`前缀普通匹配与普通匹配`) > 正则匹配
注意:
1.当有两段`前缀普通匹配或普通匹配`都匹配上,取匹配字符长的。
2.当有两段正则匹配都匹配上,取代码配置在最上面的。
3.当`普通匹配`就算`精准匹配`上,解析也不会马上结束,还得判断正则匹配是否匹配,正则匹配存在立马覆盖普通匹配。
4.当`前缀普通匹配`不是`精准匹配`匹配上的,也得判断正则匹配是否匹配,正则匹配存在立马覆盖前缀普通匹配。
官方原话(To find location matching a given request, nginx first checks locations defined using the prefix strings (prefix locations). Among them, the location with the longest matching prefix is selected and remembered.Then regular expressions are checked, in the order of their appearance in the configuration file. The search of regular expressions terminates on the first match, and the corresponding configuration is used. If no match with a regular expression is found then the configuration of the prefix location remembered earlier is used.)
文笔不好,理解的也浅,如有错误欢迎指出。
转发请注明出处!