為什麼 .htaccess 中的重定向不起作用?
我有一個 Wordpress 網站。我想將 .php 網址重定向到沒有 .php 後綴的網址。.htaccess 如下:
# BEGIN WordPress <IfModule mod_rewrite.c> RewriteEngine On RewriteRule ^(.*)\.php$ "$1" [R=301,L,NC] RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </IfModule> # END WordPress
但是當我訪問https://www.example.com/somepage.php時,頁面無法顯示。瀏覽器中顯示以下錯誤:
The page isn’t redirecting properly An error occurred during a connection to www.example.com. This problem can sometimes be caused by disabling or refusing to accept cookies.
地址欄中的 url 變為 https://www.example.com/index。
如果我將重寫規則更改為:
# BEGIN WordPress <IfModule mod_rewrite.c> RewriteEngine On RewriteRule ^(.*)\.html$ "$1" [R=301,L,NC] RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </IfModule> # END WordPress
並訪問https://www.example.com/somepage.html>,成功重定向到<https://www.example.com/somepage,網頁正常顯示。為什麼?
因為,由於重定向是無條件的,所以在 URL 被重寫後,您最終會再次重定向
index.php
(WordPress 前端控制器)。當您請求時
/somepage.php
:
- 您被重定向到
/somepage
(根據第一條規則)。重定向響應被發送回客戶端。- 在第二個請求中,由最後一條規則在
/somepage
內部重寫。/index.php
然後重寫引擎重新開始(在目錄上下文中)……/index.php
被重定向到/index
(根據第一條規則)。重定向響應被發送回客戶端。- 在第三次請求
/index
中,最後一次重寫在內部/index.php
重寫。然後重寫引擎重新開始……- 轉到 3(陷入無休止的重定向循環)。
在目錄上下文(如
.htaccess
)中,重寫引擎不會簡單地通過腳本。它循環直到 URL 不變地通過。(除非您END
在 Apache 2.4 上使用該標誌,否則會發生外部 3xx 重定向。)更改為 remove
.html
可以正常工作,因為您正在重寫為/index.php
,它不以 結尾.html
,因此重定向指令(即 removes.html
)不匹配。要解決此問題,您需要避免重定向重寫的請求。您可以通過以下任一方式執行此操作:
- 在最後一次重寫時使用
END
標誌(Apache 2.4+),而不是L
防止重寫引擎的任何進一步循環。儘管您應該避免更改現有的 WordPress 指令(見下文),因此這可能不是首選選項。這也不適用於 Apache 2.2。- 或者,針對伺服器變數檢查
.php
副檔名THE_REQUEST
(它包含 HTTP 請求標頭的初始行,並且在重寫請求時不會更改)。例如:# Remove ".php" extension on "direct" (not rewritten) requests only RewriteCond %{THE_REQUEST} [A-Z]{3,7}\s/[^?]+\.php(?:\?|\s|$) [NC] RewriteRule (.+)\.php$ /$1 [R=301,L,NC]
- 或者,檢查
REDIRECT_STATUS
環境變數,它在初始請求時為空,並在第一次成功重寫時設置為 200(如 200 OK HTTP 狀態)(這比上面更複雜的正則表達式更簡單)。例如:# Remove ".php" extension on "direct" (not rewritten) requests only RewriteCond %{ENV:REDIRECT_STATUS} ^$ RewriteRule (.+)\.php$ /$1 [R=301,L,NC]
但是,您不應該編輯該
# BEGIN WordPress
部分內的程式碼,因為 WordPress 本身會嘗試維護它,並且以後可能會覆蓋此程式碼。此規則需要放在評論標記之前。# BEGIN WordPress
您無需重複RewriteEngine On
文件稍後出現的指令(在 WordPress 部分中)。您需要在測試之前清除瀏覽器記憶體,因為錯誤(永久)重定向可能已被瀏覽器記憶體。首先使用 301(臨時)重定向進行測試以避免記憶體問題。
但是,僅此一項並不允許您訪問
.php
沒有.php
副檔名的文件。由於無副檔名 URL 需要在內部重寫回.php
文件。