寫在前面的話
在 nginx 中,我們很多時候都有一個疑問,在 proxy_pass 或者 root 或者 location 后面需不需要加上 /,加和不加有啥區別。
root / alias 后面的 /
root 和 alias 都是指向目錄,所以后面是否存在 / 沒有影響:
server { listen 8082; server_name localhost; location ^~ /root/ { root /data/www/root/; index index.html index.htm; } location ^~ /alias/ { alias /data/www/alias/; index index.html index.htm; } }
我們這里加不加紅色的 / 都一樣的結果。
location 后面的 /
在 location 中也存在是否添加 / 的情況:
server { listen 8082; server_name localhost; location ^~ /alias/ { echo "WITH: /"; } location ^~ /alias { echo "WITHOUT: /"; } }
此時兩種匹配就有了兩個含義,前者只能匹配 /alis/123 這樣的,而后者可以匹配 /alias123,也可 /alias/123 這樣的。
但是當兩者同時在一個 server 中由於匹配精確度越高優先級越高的原因,后者匹配不到 /alias/123
proxy_pass 后面的 /
這個才是我們這次說明的重點,也是最為復雜的:
我們新建這樣的目錄結構,然后配置 nginx:
server { listen 7000; server_name localhost; location / { root /data/www/proxy_pass; } }
此時我們可以訪問這 4 個 html 文件測試:
這個時候我們做反向代理:
# 代理不帶項目名稱,沒有 / server { listen 7001; server_name locahost; location /proxy/ { proxy_pass http://127.0.0.1:7000; } } # 代理不帶項目名稱,但是有 / server { listen 7002; server_name locahost; location /proxy/ { proxy_pass http://127.0.0.1:7000/; } } # 代理帶項目名稱,沒有 / server { listen 7003; server_name locahost; location /proxy/ { proxy_pass http://127.0.0.1:7000/other; } } # 代理帶項目名稱,但是有 / server { listen 7004; server_name locahost; location /proxy/ { proxy_pass http://127.0.0.1:7000/other/; } }
此時我們訪問測試同一 URI 不同端口:
結論:
在 proxy_pass 中,當我們不是 / 匹配而是帶有自定義項目名匹配的時候:
1. proxy_pass 后面帶 /,我們的自定義的項目名就不會被視作路徑的一部分去查找后端。
2. proxy_pass 后面不帶 /,我們自定義的項目名會當成路徑的一部分添加到代理后端的查找中。
當我們在 proxy_pass 代理的導致中還包含項目名稱的時候:
1. 當后面還跟了項目名,我們自定義的匹配項目名就都不會再作為請求的一部分去查找后端。
2. 當后面的項目名不帶 / 的時候,除去我們自定義部分,后面的 URI 會直接拼接到我們 proxy_pass 上面,由於他們之間沒有 / 分隔,所以會組成一個新的路徑去查后端。
3. 當后面的項目帶 / 的時候,則會在拼接的時候相當於多了個 / 的分隔。
小結
這個 / 就很小的一個符號,但是可能造成我們配置的東西完全不符合我們的需求,特別是第三個 proxy_pass 的。