[toc]
nginx location
匹配语法
location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
location [匹配模式] uri {
...
}
location匹配规则
匹配规则总览
匹配模式 | 匹配符 | 优先级 |
---|---|---|
精确匹配 | = | 1 |
前缀匹配 | ^~ | 2 |
正则匹配 | ~ | 3 |
正常匹配 | uri | 4 |
全匹配(通用匹配) | / | 5 |
匹配规则细分
匹配符 | 匹配规则 | 优先级 |
---|---|---|
= | 精确匹配 | 1 |
^~ | 以某个字符串开头 | 2 |
~ | 区分大小写的正则匹配 | 3 |
~* | 不区分大小写的正则匹配 | 4 |
!~ | 区分大小写不匹配的正则 | 5 |
!~* | 不区分大小写不匹配的正则 | 6 |
/ | 通用匹配,任何请求都会匹配到 | 7 |
location匹配优先级
路径匹配优先级
- 精确匹配 > 前缀匹配 > 正则匹配 > 正常匹配 > 全匹配
匹配示例
精确匹配
⚠️server_name _ 中的_只是一个无效域名的表示方法
编辑nginx配置文件
server {
listen 80;
server_name _;
# 第1段
location /nginx {
#return 200 "aaa";
root /data/nginx/html4/;
index index.html;
}
# 第2段
location = /nginx {
#return 200 "bbb";
root /data/nginx/html3/;
index index.html;
}
}
创建网站根目录
mkdir -p /data/nginx/html{3,4}/nginx
echo 'html3' >/data/nginx/html3/nginx/index.html
echo 'html4' >/data/nginx/html4/nginx/index.html
访问测试
$ curl 127.0.0.1/nginx
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
$ curl 127.0.0.1/nginx/
html4
精确匹配中 /nginx/
中优先匹配到第2段,再访问 /nginx/index.html
,此次内部跳转uri已经是 /nginx/index.html
,而非 =
的,最终访问结果是第1段中的 index.html
。
结论:精确匹配区分大小写,不能使用正则,访问的URI必须完全与 =
后面的一致,多一个 /
或者少一个 /
,都是不可以的
前 缀匹配
编辑nginx配置文件
server {
listen 80;
server_name _;
location ^~ /nginx/ {
rewrite ^ https://www.163.com break;
}
location ^~ /nginx/bcd/ {
rewrite ^ https://www.qq.com break;
}
location ^~ /Abc/ {
rewrite ^ https://www.sina.com.cn break;
}
}
访问测试
访问127.0.0.1/nginx/
,在终端中会返回302,在浏览器中会跳转到www.163.com
$ curl 127.0.0.1/nginx/
<html>
<head><title>302 Found</title></head>
<body>
<center><h1>302 Found</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
访问127.0.0.1/nginx/bcd/
,在终端中会返回302,在浏览器中会跳转到www.qq.com
⚠️如果bcd后边不加 /
,跳转页面是www.163.com
,即只匹配前缀 /nginx
$ curl 127.0.0.1/nginx/bcd/
<html>
<head><title>302 Found</title></head>
<body>
<center><h1>302 Found</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
访问一个不存在的页面127.0.0.1/nginx/abcd/
,在终端中会返回302,在浏览器中会跳转到www.163.com
$ curl 127.0.0.1/nginx/abcd/
<html>
<head><title>302 Found</title></head>
<body>
<center><h1>302 Found</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
访问127.0.0.1/Abc/
,在终端中会返回302,在浏览器中会跳转到www.sina.com.cn
$ curl 127.0.0.1/nginx/abc/
<html>
<head><title>302 Found</title></head>
<body>
<center><h1>302 Found</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
结论:前缀匹配不能使用正则,区分大小写,只要前缀相同,都可以匹配成功,不管后面有没有字符,保证前缀相同即可
正则匹配
编辑nginx配置文件
server {
listen 80;
server_name _;
location ~ /[a-z]nginx/ {
rewrite ^ https://www.baidu.com break;
}
location ~* /[a-z]nginx/ {
rewrite ^ https://www.163.com break;
}
}
访问测试
访问127.0.0.1/anginx/
,在终端中会返回302,在浏览器中会跳转到www.baidu.com
$ curl 127.0.0.1/anginx/
<html>
<head><title>302 Found</title></head>
<body>
<center><h1>302 Found</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
访问127.0.0.1/anginx/abc
在终端中会返回302,在浏览器中会跳转到www.baidu.com
$ curl 127.0.0.1/anginx/abc/
<html>
<head><title>302 Found</title></head>
<body>
<center><h1>302 Found</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
访问127.0.0.1/Anginx/
,在终端中会返回302,在浏览器中会跳转到www.163.com
$ curl 127.0.0.1/Anginx/
<html>
<head><title>302 Found</title></head>
<body>
<center><h1>302 Found</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
结论:正则匹配 ~
区分大小写,~*
不区分大小写, 并且与前缀匹配比较类似,只需要匹配模式开头部分,这两种同时存在时,优先匹配区分大小写的
正常匹配
- 正常匹配就是匹配模式为空的匹配规则
编辑 nginx配置文件
server {
listen 80;
server_name _;
# 第1段
location /nginx/ {
rewrite ^ https://www.baidu.com break;
}
# 第2段
location /[0-9]nginx/ {
rewrite ^ https://www.qq.com break;
}
}
访问测试
访问127.0.0.1/nginx/
,在终端中会返回302,在浏览器中会跳转到www.baidu.com
$ curl 127.0.0.1/nginx/
<html>
<head><title>302 Found</title></head>
<body>
<center><h1>302 Found</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
上述配置文件中第2段访问不生效,404
⚠️location ^~ /nginx/
与location /nginx/
不能同时出现
结论:正常匹配与前缀匹配的差别,只在于优先级
全匹配(通用匹配)
编辑nginx配置文件
server {
listen 80;
server_name _;
location / {
root /data/nginx/html;
index index.html index.htm;
}
}
全匹配没有匹配模式,并且匹配的uri仅是一个斜杠/,通常用在一个默认页面的地方
命名匹配
命名匹配一般用于静态页面或者错误页面(404,500等),并且这个命名匹配中,不允许有alias。
error_page 404 = @notfound;
location @notfound {
rewrite ^ https://www.baidu.com break;
}
优先级验证综合实验
编辑nginx配置文件
⚠️前缀匹配和正常匹配不能同时存在
server {
listen 80;
server_name _;
# 全匹配,这里/data/nginx/html/下面有一个nginx文件夹,里面有index.html,内容是nginx location test
location / {
root /data/nginx/html;
index index.html;
}
# 正常匹配
location /nginx/ {
rewrite ^/nginx/$ https://www.sina.com.cn/ break;
}
# 正则匹配
location ~ /[a-z]ginx/ {
rewrite ^/nginx/$ https://www.163.com/ break;
}
# 前缀匹配
location ^~ /nginx/ {
rewrite ^/nginx/$ https://www.baidu.com/ break;
}
# 精确匹配
location = /nginx/ {
rewrite ^/nginx/$ https://www.qq.com/ break;
}
}
创建网站根目录
mkdir -p /data/nginx/html/nginx
echo 'nginx location test' > /data/nginx/html/nginx/index.html
第一步、把正常匹配注释掉,留下前缀匹配,然后浏览器访问IP/nginx/
,第一次返回的结果是跳转到了www.qq.com
,证明了=
精确匹配优先级是最大的
第二步、把精确匹配注释掉,然后浏览器访问IP/nginx/
,结果是跳转到了www.baidu.com
,证明了^~
前缀匹配优先级是仅次于精确匹配
第三步、因为前缀匹配和正常匹配不能同时存在,所以这一步比较第一步和第二步,还是把精确匹配注释掉,这次把前缀匹配注释掉,把正常匹配注释打开,结果是跳转到了www.163.com
,说明正则匹配的优先级是大于正常匹配的,同时也验证了前缀匹配优先级第2,正则匹配优先级第3,正常匹配优先级第4
第四步、现在只剩下全匹配了,所以全匹配的优先级最低
结论:各匹配优先级如下 精确匹配 > 前缀匹配 > 正则匹配 > 正常匹配 > 全匹配
匹配原则除了这个优先级外,还有一个就是在相同指令模式匹配中,匹配度最大的URI优先
root与alias
nginx配置 location规则中的 uri 往往都是匹配一个目录。
root
编辑nginx配置文件
server {
listen 80;
server_name _;
location /nginx/ {
root /data/nginx/html/;
index index.html index.htm;
}
}
使用root关键字指定网站根目录
当访问127.0.0.1/nginx/index.html
时,如果/data/nginx/html/
这个目录下没有nginx/index.html
或者没有nginx目录,则会报错404
原因是使用root指定目录时,目录下边要包 括location后面的uri,否则就会报错
使用root指定目录时,不会将location uri配置的路径去掉,即访问的路径是/data/nginx/html/nginx
访问测试
#不创建目录nginx
mkdir -p /data/nginx/html/
echo 'abc' >/data/nginx.html/index.html
#访问报错404
$ curl 127.0.0.1/nginx/
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
alias
编辑nginx配置文件
server {
listen 80;
server_name _;
location /nginx/ {
alias /data/nginx/html/;
index index.html index.htm;
}
}
使用alias关键字指定网站根目录
当访问127.0.0.1/nginx/index.html
时,只要保证alias指定的目录中有index.html即可,即使没有目录nginx,它会将location uri配置的路径去掉,实际访问的就是/data/nginx/html/index.html
访问测试
#不创建目录nginx
mkdir -p /data/nginx/html/
echo 'abc' >/data/nginx.html/index.html
$ curl 127.0.0.1/nginx/
abc
结论:root 指定的目录中,需要location中的 uri 路径目录确实存在,alias 指定的目录中不需要 location中的uri 路径目录存在
代理服务器 proxy_pass 中有无 /
实验环境
角色 | 主机名 | IP |
---|---|---|
真实web | web01 | 10.0.0.10 |
nginx代理 | nginx-proxy | 10.0.0.51 |
后端真实web服务配置
后端真实web服务nginx 10.0.0.10配置
server {
listen 80;
server_name _;
location /nginx/ {
root /data/nginx/html/;
index index.html index.htm;
}
location /ng/ {
root /data/nginx/html/;
index index.html index.htm;
}
location /k8s/ {
root /data/nginx/html/;
index index.html index.htm;
}
}
创建网站根目录
mkdir -p /data/nginx/html/{nginx,ng,k8s}
echo 'nginx' >/data/nginx/html/nginx/index.html
echo 'ng' >/data/nginx/html/ng/index.html
echo 'k8s' >/data/nginx/html/k8s/index.html
访问测试
$ curl 127.0.0.1/nginx/
nginx
$ curl 127.0.0.1/ng/
ng
$ curl 127.0.0.1/k8s/
k8s
proxy_pass无目录无/
代理服务器nginx 10.0.0.51配置中 proxy_pass
无'/'验证
server {
listen 80;
server_name _;
location /nginx {
#没有/指的是proxy_pass后边的url没有/后缀
proxy_pass http://10.0.0.10;
}
}
访问测试
$ curl 10.0.0.51/nginx/
nginx
$ curl -L 10.0.0.51/nginx
nginx
真实web服务10.0.0.10nginx访问日志如下
10.0.0.51 - - [18/Jun/2020:17:46:53 +0800] "GET /nginx/ HTTP/1.0" 200 6 "-" "curl/7.29.0" "-"
结论:如果 proxy_pass
反向代理中,在server后面没有 /
反斜杠的话,访问的是 http://10.0.0.10/nginx/index.html
,它会去上游真实服务器去匹配代理服务器上面location URI
proxy_pass无目录有/
代理服务器nginx 10.0.0.51配置中 proxy_pass
'/'验证
server {
listen 80;
server_name _;
location /nginx {
#有/指的是proxy_pass后边的url有/后缀
proxy_pass http://10.0.0.10/;
}
}
访问测试
因为访问的是真实服务器的/,但是并没有在真实服务器根中写入访问页面
$ curl 10.0.0.51/nginx/
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
真实web服务10.0.0.10nginx访问日志如下
10.0.0.51 - - [18/Jun/2020:17:51:32 +0800] "GET / HTTP/1.0" 404 153 "-" "curl/7.29.0" "-"
结论:如果 proxy_pass
反向代理中,在server后面有 /
反斜杠的话,访问的是 http://10.0.0.10/index.html
,它会忽略掉代理服务器上面location中的URI,直接访问代理服务器上面的 /
proxy_pass有目录无/
代理服务器10.0.0.51proxy_pass
后面增加目录,但不加 /
server {
listen 80;
server_name _;
location /nginx/ {
proxy_pass http://10.0.0.10/nginx;
}
}
访问测试
因为访问的是真实服务器的/,但是并没有在真实服务器根中写入访问页面
$ curl 10.0.0.51/nginx/
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
真实web服务10.0.0.10nginx访问日志如下
10.0.0.51 - - [18/Jun/2020:18:04:40 +0800] "GET /nginx HTTP/1.0" 404 153 "-" "curl/7.29.0" "-"
结论:如果 proxy_pass
反向代理中,在server后面有URI, 但没有 /
反斜杠的话,访问的是 http://10.0.0.10/nginx
,它会去上游真实服务器去匹配代理服务器上面的URI
proxy_pass有目录有/
代理服务器10.0.0.51proxy_pass
后面增加目录并且加 /
server {
listen 80;
server_name _;
location /nginx/ {
proxy_pass http://10.0.0.10/nginx/;
}
}
访问测试
$ curl 10.0.0.51/nginx/
nginx
真实web服务10.0.0.10nginx访问日志如下
10.0.0.51 - - [18/Jun/2020:17:58:47 +0800] "GET /nginx/ HTTP/1.0" 200 6 "-" "curl/7.29.0" "-"
结论:如果 proxy_pass
反向代理中有目录,并且有 /
反斜杠的话,访问的是http://10.0.0.10/nginx/index.html
,它会忽略掉代理服务器上面location中的URI,直接访问代理服务器上面的目录+ /
的形式