![Nginx 不选择具有最长前缀的位置](https://linux22.com/image/778174/Nginx%20%E4%B8%8D%E9%80%89%E6%8B%A9%E5%85%B7%E6%9C%89%E6%9C%80%E9%95%BF%E5%89%8D%E7%BC%80%E7%9A%84%E4%BD%8D%E7%BD%AE.png)
在这个简化的 nginx 设置中,我有两个 nginx 位置块,一个用于 SSL 证书更新,一个用于快速代理(用于 uwsgi/Django )。
当通过 acme.sh 进行 SSL 证书更新时,它会将文件放入其中/var/www/example.com/public/.well-known/acme-challenge/
,然后测试它们是否可用。但是,快速代理 (Django) 正在处理请求,/.well-known/acme-challenge/.......
而不是location = /\.well-known/acme-challenge/
位置块。
我该如何告诉 nginx 使用正确的块?如果我删除快速代理位置块,则该location = /\.well-known/acme-challenge/
块可以正常工作。
配置如下:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2; # For IP6
server_name www.example.com;
charset utf-8;
root /var/www/example.com/public;
# acme.sh SSL certificate issues
location /\.well-known/acme-challenge/ {
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include /home/michael/project/conf/uwsgi/params;
}
这nginx 文档说:
当 nginx 选择一个位置块来处理请求时,它首先检查指定前缀的位置指令,记住前缀最长的位置,然后检查正则表达式。如果与正则表达式匹配,nginx 将选择此位置,否则,它将选择先前记住的位置。
对我来说/\.well-known/acme-challenge/
这是最长的前缀,所以它应该“获胜”。
答案1
你看过location
指示?
~*
位置既可以通过前缀字符串定义,也可以通过正则表达式定义。正则表达式使用前面的“ ”修饰符(用于不区分大小写的匹配)或“~
”修饰符(用于区分大小写的匹配)指定。为了找到与给定请求匹配的位置,nginx 首先检查使用前缀字符串(前缀位置)定义的位置。其中,选择并记住具有最长匹配前缀的位置。然后按照正则表达式在配置文件中出现的顺序检查正则表达式。正则表达式的搜索在第一次匹配时终止,并使用相应的配置。如果没有找到与正则表达式匹配的,则使用先前记住的前缀位置的配置。
您的location /\.well-known/acme-challenge/
字符串是前缀字符串,但您尝试将其转义.
为正则表达式。这不起作用。
对于 URL https://www.example.com/.well-known/acme-challenge/foo
...
server {
listen 443 ssl http2;
server_name www.example.com;
# 1. Prefix string, NO MATCH.
location /\.well-known/acme-challenge/ {
}
# 2. Longest matching prefix string.
location /.well-known/acme-challenge/ {
}
# 3. First case sensitive regex match.
location ~ /\.well-known/acme-challenge/ {
}
# 4. Another case sensitive regex match.
location ~ ^/\.well-known/acme-challenge/ {
}
# 5. Matching prefix string, but not the longest.
location / {
}
}
如果您拥有所有这些,则将使用正则表达式匹配 #3,因为它是第一个匹配的正则表达式。它还会与/any/path/having/.well-known/acme-challenge/in/it
#4 匹配,而 #4 仅在 URI 路径的开头匹配,类似于前缀字符串匹配。
TL;DR:#2 和 #4 是等效的,通过这两者您都可以实现您的目标。
为了完整性,评估顺序如下:
- #1 前缀,不匹配
- #2 前缀,匹配(长度=28)
- #5 前缀,匹配(长度=1)
- #3 正则表达式,匹配 => 选择
#4 不会被评估。如果没有 #3 和 #4,#2 就会获胜。