语法规则
location optional_modifier location_match {
. . .
}optional_modifier有以下几个值:
=: 精确匹配。完全相等才会进行匹配,直接用当前location处理请求^~: 前缀匹配。不会进行正则匹配,搜索到最长前缀匹配之后用当前location处理请求~: 正则匹配。区分大小写,搜索到最长前缀匹配之后用当前location处理请求~*: 正则匹配。不区分大小写,搜索到最长前缀匹配之后用当前location处理请求(none): 前缀匹配。优先级最低
匹配顺序
- 先进行精确匹配(
=),匹配之后终止搜索其他location - 然后寻找前缀匹配(
^~),匹配之后终止搜索其他location =和^~都无法匹配的情况下会按照location出现的顺序进行正则匹配(~和~*)- 最后是
(none)匹配
下面验证一下匹配顺序,通过输出 X-location来判断哪个location起作用
情形一:只有精确匹配(=)
...
location = /baidu {
rewrite ^/baidu(.*) /$1 break;
add_header X-location '= /baidu';
proxy_pass https://www.baidu.com;
}
...curl -I http://localhost/baidu
HTTP/1.1 200 OK
Server: nginx/1.17.4
...
X-location: = /baidu情形二:^~和正则匹配共同起作用时,用^~处理请求。尽管正则匹配的location_match更长
...
location ~ ^/baidu {
rewrite ^/baidu /$1 break;
add_header X-location '~ ^/baidu';
proxy_pass https://www.baidu.com;
}
location ^~ /bai {
rewrite ^/baidu /$1 break;
add_header X-location '^~ /bai';
proxy_pass https://www.baidu.com;
}
...curl -I -X GET http://localhost/baidu
HTTP/1.1 200 OK
Server: nginx/1.17.4
...
X-location: ^~ /bai情形三:(none)和正则匹配共同起作用时,用最先出现正则匹配处理请求。尽管(none)的location_match更长
...
location /baidu {
rewrite ^/baidu /$1 break;
add_header X-location '/baidu';
proxy_pass https://www.baidu.com;
}
location ~ ^/bai {
rewrite ^/baidu /$1 break;
add_header X-location '~ ^/bai';
proxy_pass https://www.baidu.com;
}
location ~* ^/baid {
rewrite ^/baidu /$1 break;
add_header X-location '~* ^/baid';
proxy_pass https://www.baidu.com;
}
...curl -I http://localhost/baidu
HTTP/1.1 200 OK
Server: nginx/1.17.4
...
X-location: ~ ^/bai更换一下正则匹配的先后顺序
...
location /baidu {
rewrite ^/baidu /$1 break;
add_header X-location '/baidu';
proxy_pass https://www.baidu.com;
}
location ~* ^/baid {
rewrite ^/baidu /$1 break;
add_header X-location '~* ^/baid';
proxy_pass https://www.baidu.com;
}
location ~ ^/bai {
rewrite ^/baidu /$1 break;
add_header X-location '~ ^/bai';
proxy_pass https://www.baidu.com;
...curl -I http://localhost/baidu
HTTP/1.1 200 OK
Server: nginx/1.17.4
...
X-location: ~* ^/baidURI对proxy_pass的影响
- 如果
proxy_pass有URI,location_match部分会替换成URI - 如果
proxy_pass无URI,则会传递完整的请求URI
具体Demo,以下例子中URI为/
情形一:proxy_pass无URI,location_match有尾斜杠
location /api/ {
proxy_pass http://www.baidu.com;
}
#http://localhost/api/ => http://www.baidu.com/api/
#http://localhost/api/xx => http://www.baidu.com/api/xx
#http://localhost/api-xx => 不匹配情形二:proxy_pass无URI,location_match无尾斜杠
location /api {
proxy_pass http://www.baidu.com;
}
#http://localhost/api/ => http://www.baidu.com/api/
#http://localhost/api/xx => http://www.baidu.com/api/xx
#http://localhost/api-xx => http://www.baidu.com/api-xx情形三:proxy_pass有URI,location_match有尾斜杠
location /api/ {
proxy_pass http://www.baidu.com/;
}
#http://localhost/api/ => http://www.baidu.com/
#http://localhost/api/xx => http://www.baidu.com/xx
#http://localhost/api-xx => 不匹配情形四:proxy_pass有URI,location_match无尾斜杠。容易踩坑,应避免使用。
location /api {
proxy_pass http://www.baidu.com/;
}
#http://localhost/api => http://www.baidu.com/
#http://localhost/api/ => http://www.baidu.com//
#http://localhost/api/xx => http://www.baidu.com//xx
#http://localhost/api-xx => http://www.baidu.com/-xx内部重定向指令
index: 只处理以尾斜杠结束的请求。按指定顺序索引文件
/请求会被内部重定向到/index.html
location = / {
index index.html;
}
location / {
...
}try_files: 按指定顺序进行索引,可以索引文件和目录,存在尾斜杠就会索引目录
设置默认图片
location /images/ {
try_files $uri /images/default.gif;
}
location = /images/default.gif {
expires 30s;
}按顺序索引多个文件,实在找不到就返回404
location / {
try_files $uri $uri/index.html $uri.html =404;
}前端 SPA 部署
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
}rewrite: 使用正则表达式替换请求URI,可通过设置last,break,redirect和permanent来决定进一步的处理方式
将/v2-web或者/v2-web/替换为空, 并继续匹配其他location
location ~ ^/v2-web/? {
rewrite ^(/v2-web/?)(.*) /$2 last;
}将/v2-web或者/v2-web/替换为空, 停止匹配其他location
location ~ ^/v2-web/? {
rewrite ^(/v2-web/?)(.*) /$2 break;
proxy_pass http://www.baidu.com;
}302重定向到百度
location ~ ^/baidu {
rewrite ^/(.*)$ http://www.baidu.com redirect;
}301重定向到百度
location ~ ^/baidu {
rewrite ^/(.*)$ http://www.baidu.com permanent;
}error_page: 不同的错误码响应不同的处理结果
404错误由http://backend进行响应
location / {
error_page 404 = @fallback;
}
location @fallback {
proxy_pass http://backend;
}参考资料
proxy_pass url 反向代理的坑
proxy_pass反向代理配置中url后面加不加/的说明
nginx的proxy_pass和 location为正则表达式的问题
Understanding Nginx Server and Location Block Selection Algorithms
How to stop nginx 301 auto redirect when trailing slash is not in URI?
本文由 Chakhsu Lau 创作,采用 知识共享署名4.0 国际许可协议进行许可。
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。