Nginx的location指令配置
source link: http://blog.7rule.com/2018/02/20/nginx-location.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Nginx的location指令配置
Feb 20, 2018
在编写nginx配置中,正确的配置location指令是相当重要的。笔者在一次问题的排查中仔细研究了下这个指令的规则和使用方法,在这里和大家分享一下,如有不正确的地方还望指正。
location [ 限定符 ] 规则uri { 指令集 }
在一个请求的处理流程中,nginx会启动一个location的查找过程,在这个过程中nginx会根据一定的规则用请求的request_uri有选择的去匹配这些定义好的规则uri,之后会找到要应用的唯一的location,并应用这个location定义的指令集中的指令。
这里面最关键的地方,就是location的查找过程是如何进行的。要明白这个过程,首先需要知道规则uri是如何定义的。
规则uri
规则uri分为三种类型,nginx对这几种类型执行的匹配方法是不同的:
1. 对限定符为=
的规则执行完全匹配
完全匹配例:location = index.php {},那么仅有请求:http://domain/index.php才能匹配,http://domain/index.phpp或http://domain/iindex.php这种均无法匹配。
2. 对限定符为^~
或没有限定符规则执行前缀匹配。
前缀匹配例:location /abc {}或location ^~ /abc {},那么请求:http://domain/abcd、http://domain/abc.php这种均能匹配。
3. 对限定符为~
或~*
的规则执行正则匹配。
正则匹配例:location ~ .php$ {},那么请求:http://domain/abc.php、http://domain/abcd.php这种均可以匹配。
location的查找过程
首先会对所有的等号规则
和前缀规则
进行一次匹配筛选。nginx会在所有的前缀匹配中找到一个最长的
匹配,然后记住这个匹配的location。之后会根据这个匹配规则是否有限定符
来决定之后的行为:
-
如果是
等号规则
匹配到的,nginx会立即结束查找过程,这个location就是最终结果。 -
如果匹配到的规则被限定符
^~
修饰,则nginx也会结束这个查找过程,这个location就是最终结果。 -
如果没有找到匹配或是匹配项没有被限定符修饰,nginx就会进入
正则规则
的匹配筛选过程。在这个过程中,nginx会按照规则uri在配置中定义的顺序来进行匹配,只要匹配到其中一个,nginx就会立即结束这个匹配过程,这个location也会是最终location。如果没有能找到一个正则匹配,但是之前的前缀匹配成功,那么之前记住的前缀匹配结果则会成为最终结果。
通过上面的查找过程,如果成功找到匹配的location,则会执行执行这个location定义的指令集中的指令。
下面举几个例子来看一下:假设用户均访问http://www.vmc7.com/abc
1. =
命中,跳过正则匹配
server {
listen 80;
server_name www.vmc7.com;
location /abc {}
location = /abc {}
location ~ /abc {}
}
2. ^~
命中,跳过正则匹配
server {
listen 80;
server_name www.vmc7.com;
location /ab {}
location ^~ /abc {}
location ~ /abc {}
}
3. 正则
命中1,正则匹配优先于前缀匹配
server {
listen 80;
server_name www.vmc7.com;
location /abc {}
location ~ /ab.* {}
}
4. 正则
命中2,正则按顺序匹配
server {
listen 80;
server_name www.vmc7.com;
location /ab {}
location ~ /ab.* {}
location ~ /abc {}
}
5. 前缀
命中,正则匹配不到,使用之前命中的前缀匹配
server {
listen 80;
server_name www.vmc7.com;
location /abc {}
location ~ /ef.* {}
}
最后附上伪代码用以描述整个过程
location = findLocation();
if (location != null) {
runLocationCmdSet();
}
function findLocation()
{
finalLocation = null;
prefixLocation = null;
regexLocation = null;
prefixLocation = findByPrefix();
if (prefixLocation != null) {
if (preceding(prefixLocation) == '=') {
return prefixLocation;
}
if (preceding(prefixLocation) == '^~') {
return prefixLocation;
}
}
regexLocation = findByRegex();
finalLocation = (regexLocation == null) ? prefixLocation : regexLocation;
return finalLocation;
}
function findByPrefix()
{
result = null;
maxLength = 0;
for (location in allPrefixLocation) {
if ((matchLength = prefixMatch(location))!= 0) {
if (matchLength > maxLength) {
maxLength = matchLength;
result = location;
}
}
}
return result;
}
function findByRegex()
{
for (location in allRegexLocation) {
if (regexMatch(location)) {
return location;
}
}
return null;
}
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK