環境:nginx 版本為 1.2.6
最近在做專案時遇到一個奇怪的問題,因為要重新設計url,所以用到了以下nginx重寫規則:
if (-f $request_filename/index.html){ rewrite (.*) /index.html break; } if (-f $request_filename/index.php){ rewrite (.*) /index.php; } if (!-f $request_filename){ rewrite (.*) /index.php; }
這個重寫規則已經普遍使用,我也不知道有沒有什麼地方不妥~(求指點)
在我沒有使用這些規則時,訪問伺服器上一個存在的目錄時會自動加個斜杠,這時觸發了nginx自動的rewrite規則,這很正常,沒有問題。
但是我加了上面這些規則後,訪問伺服器上已經存在的資料夾時就不會自動加斜線了,而且,在我反覆測試後,發現是第2、3條規則在作怪:
1、如果只把第2條規則刪除,那麼不無論你資料夾存不存在都會檢測成不存在,而且不會加斜杠,並且會直接進入第3條規則,最終匹配進入index. php,可以得知,此時是按文件來處理的。
2、如果把第2條規則刪除,第3條規則對檔案的判斷 -f
改為 -e
,即檔案或資料夾:
if (!-e $request_filename){ rewrite (.*) /index.php; }
這時,問題得以解決,目錄存在時會自動加斜杠,不存在時會匹配進入到index.php,這正是我想要的。
我很不解,求大師指點,為什麼會是這個樣子呢?
另外,由於專案原有的一些問題,在第3條規則裡面還有一大坨其它針對性的重寫規則,所以我並不希望在輸入的是資料夾而且存在時還會進入第3條規則去匹配規則,雖然效能影響並不大。
經過多次測試,自己搞清楚了。
這三條規則並沒有什麼問題,第二條也不是我之前所說的有什麼詭異的地方。
首先,nginx會根據用戶自訂的規則進行匹配,當你輸入的路徑存在且在最後不含有斜杠時,
由於我這個資料夾下存在index.php,所以
$request_filename/index.php
匹配第二条规则成功,注意这里的/
,然後進行之後的配對。也就是說,只要這個資料夾是存在的,而這個資料夾下有 index.html 或 index.php 就會符合我上面給的第一個或第二條規則,這沒有任何疑問。所以,你如果想要在資料夾存在時不會進行第一或二條規則之後的配對且會自動加上斜杠,解決辦法是在第一條規則之前加上一條對資料夾的判斷:
這條規則的意思是,如果文件夾存在且沒有斜杠時自動加斜杠並進行301跳轉,OK,問題解決。
最後一條的邏輯是,在不滿足前面條件的情況下,「如果存取的路徑不是檔案」就會自動跳到/index.php。
建議:在第三條之前插入一句 -e 偵測是否是資料夾,如果是,自動加斜線,break。
未測試,僅供參考。