首先,由于网上介绍的location的匹配顺序听起来都太笼统,不是很明白,因此就location的匹配顺序,做了个实验,location的配置如下:
server {
listen 8080;
server_name localhost;
location = / {
default_type text/html;
return 200 "main";
}
location / {
default_type text/html;
return 200 "default main";
}
location ^~ /test {
default_type application/json;
return 200 '{"test": "Hello World!"}';
}
location /test/hello/world {
default_type text/html;
return 200 "hello world";
}
location ~* \.(png|gif)$ {
default_type text/html;
return 200 "images";
}
location ~* ^/hello {
default_type text/html;
return 200 "test hello";
}
}
然后我们执行不同的url,观看匹配结果。
#返回结果:main
curl 127.0.0.1:8080
#返回结果:{"test": "Hello World!"}
curl 127.0.0.1:8080/test
#返回结果:hello world
curl 127.0.0.1:8080/test/hello/world
#返回结果:images
curl 127.0.0.1:8080/1.png
#返回结果:{"test": "Hello World!"}
curl 127.0.0.1:8080/test/1.png
#返回结果:{"test": "Hello World!"}
curl 127.0.0.1:8080/test/hello
#返回结果:images
curl 127.0.0.1:8080/test/hello/world/1.png
#返回结果:default main
curl 127.0.0.1:8080/noLoction
#返回结果:test hello
curl 127.0.0.1:8080/hello
#返回结果:images
curl 127.0.0.1:8080/hello/1.png
根据上述结果和网上的笼统描述,我们可以总结location的匹配规则:
1、检查以=定义的精确匹配,匹配成功直接结束,否则到2;
2、检查前缀匹配,获得最长的前缀的匹配规则,如果该规则以^~开头,那么直接结束,否则记录获得的最长前缀结果,到3;
3、检查正则匹配,按照顺序,一旦匹配成功就结束,匹配失败则到4;
4、返回2中获得的最长前缀结果。
uri | location | 匹配逻辑 |
---|---|---|
/ | location = / | 使用=定义的精确匹配,匹配成功直接结束(最优先) |
/test | location ^~ /test | =定义的location匹配不上,然后前缀匹配,最长的前缀就是/test,以^~开始,所以不再进行正则匹配,返回最长前缀匹配结果 |
/test/hello/world | location /test/hello/world | =定义的location匹配不上,然后前缀匹配,最长的前缀/test/hello/world,然后进行正则匹配,匹配不上,返回最长前缀匹配结果 |
/1.png | location ~* .(png|gif)$ | =定义的location匹配不上,然后前缀匹配,最长的前缀/,然后进行正则匹配,匹配到.(png|gif)$,返回正则匹配结果 |
/test/1.png | location ^~ /test | =定义的location匹配不上,然后前缀匹配,最长的前缀就是/test,以^~开始,所以不再进行正则匹配,返回最长前缀匹配结果 |
/test/hello | location ^~ /test | =定义的location匹配不上,然后前缀匹配,最长的前缀就是/test,以^~开始,所以不再进行正则匹配,返回最长前缀匹配结果 |
/test/hello/world/1.png | location ~* .(png|gif)$ | =定义的location匹配不上,然后前缀匹配,最长的前缀/test/hello/world,然后进行正则匹配,匹配到.(png|gif)$,返回正则匹配结果 |
/noLoction | location / | =定义的location匹配不上,然后前缀匹配,最长的前缀/,然后进行正则匹配,匹配不上,返回最长前缀匹配结果 |
/hello | location ~* ^/hello | =定义的location匹配不上,然后前缀匹配,最长的前缀/,然后进行正则匹配,匹配上^/hello,返回正则匹配结果 |
/hello/1.png | location ~* .(png|gif)$ | =定义的location匹配不上,然后前缀匹配,最长的前缀/,然后进行正则匹配,可以看到两个location的正则表达式.(png|gif)$ 和^/hello都可以匹配上,匹配第一个正则表达式,匹配上直接返回结果,所以最后匹配第一个定义的:location ~* .(png|gif)$ |
另外,nginx里面有很多变量,为了看明白每个变量的作用,我们调用一个url,输出所有变量的值,来看看具体内容:
curl 'http://10.0.0.1:8080/debug?name=lily&passwd=123456'
#结果如下:其中/etc/nginx/html/是nginx的默认root,ip地址都是被我改成了假的
$args: name=lily&passwd=123456 ;
$content_length: ;
$content_type: ;
$document_root: /etc/nginx/html ;
$host: 10.0.0.1 ;
$http_user_agent:curl/7.54.0 ;
$http_cookie: ;
$limit_rate: 0 ;
$request_method: GET ;
$remote_addr: 10.0.0.2 ;
$remote_port: 58328 ;
$remote_user: ;
$request_filename: /etc/nginx/html/debug ;
$scheme: http ;
$server_protocol: HTTP/1.1 ;
$server_addr: 10.0.0.1 ;
$server_name: localhost ;
$server_port: 8080 ;
$request_uri: /debug?name=lily&passwd=123456 ;
$uri: /debug ;
$document_uri: /debug ;