Nginx 沒有選擇前綴最長的位置
在這個簡化的 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/
是最長的前綴,所以它應該“贏”。
您是否查看了該
location
指令的文件?位置可以由前綴字元串或正則表達式定義。正則表達式使用前面的“
~*
”修飾符(用於不區分大小寫的匹配)或“~
”修飾符(用於區分大小寫的匹配)指定。為了找到與給定請求匹配的位置,nginx 首先檢查使用前綴字元串(前綴位置)定義的位置。其中,匹配前綴最長的位置被選中並記憶。然後按照它們在配置文件中出現的順序檢查正則表達式。正則表達式的搜尋在第一次匹配時終止,並使用相應的配置。如果找不到與正則表達式的匹配項,則使用前面記住的前綴位置的配置。
你
location /\.well-known/acme-challenge/
是一個前綴字元串,但你試圖逃避 a.
因為它是一個正則表達式。這不起作用。對於網址
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,因為它是第一個匹配的正則表達式。與僅在 URI 路徑開頭匹配的 #4 不同,它也會匹配
/any/path/having/.well-known/acme-challenge/in/it
,類似於前綴字元串匹配。TL;DR:#2 和#4 是等價的,兩者都可以實現你的目標。
為了完整起見,評估順序為:
- #1 前綴,不匹配
- #2 前綴,匹配(長度=28)
- #5 前綴,匹配(長度=1)
- #3 正則表達式,匹配 => 選擇
#4 不會被評估。沒有#3 & #4,#2 會贏。