Dot-Htaccess

為什麼 .htaccess 中的重定向不起作用?

  • December 2, 2021

我有一個 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

  1. 您被重定向到/somepage(根據第一條規則)。重定向響應被發送回客戶端。
  2. 在第二個請求中,由最後一條規則在/somepage內部重寫。/index.php然後重寫引擎重新開始(在目錄上下文中)……
  3. /index.php被重定向到/index(根據第一條規則)。重定向響應被發送回客戶端。
  4. 在第三次請求/index中,最後一次重寫在內部/index.php重寫。然後重寫引擎重新開始……
  5. 轉到 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文件。

引用自:https://serverfault.com/questions/1085093