.HTACCESS 正在建立不必要的 301 重定向鏈 - 如何刪除?

.HTACCESS 正在建立不必要的 301 重定向鏈 - 如何刪除?

我的堆疊:

  • 阿帕契/2.4.41

背景資訊:

我最近為客戶推出了一個新網站。在重新設計過程中,我們決定:

  • 切換到全站 HTTPS
  • 從 URL 中刪除 .php 副檔名
  • 切換到 CMS

舊網址範例:
http://www.example.com/courses/acme-course.php

新網址範例:
https://www.example.com/courses/acme-course

我的問題:

當使用者導航到舊 URL 之一時,會發生不必要的額外 301 重定向。

我不明白為什麼要建立額外的 301 重定向,而不是使用單一 301 重定向將使用者直接發送到正確的目標 URL。

有趣的觀察:

當我使用帶有 HTTPS 而不是 HTTP 的舊 URL 時,不會發生不必要的額外 301 重定向。

例子:
https://www.example.com/courses/acme-course.php _

使用上面的 URL 將正確執行單一 301 重新導向到正確的目標 URL:https://www.example.com/courses/acme-course

以下是 301 重定向鏈的範例:

原始請求網址:

http://www.example.com/courses/acme-course.php

1ST 301 重定向(不必要):

從:

http://www.example.com/courses/acme-course.php

到:

https://www.example.com/index.php?url=courses/acme-course.php

2ND 301 重定向(正確的最終目標 URL):

從:

https://www.example.com/index.php?url=courses/acme-course.php

到:

https://www.example.com/courses/acme-course

我的 .htaccess 程式碼:

# (1) General Settings
<IfModule mod_rewrite.c>
    Options +FollowSymLinks
    RewriteEngine On
</IfModule>

# (2) Force WWW
<IfModule mod_rewrite.c>
    RewriteCond %{HTTPS} !=off
    RewriteCond %{HTTP_HOST} !^www\. [NC]
    RewriteCond %{SERVER_ADDR} !=127.0.0.1
    RewriteCond %{SERVER_ADDR} !=::1
    RewriteRule ^ %{ENV:PROTO}://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

# (3) Force HTTPS
<IfModule mod_rewrite.c>
    RewriteCond %{HTTPS} !=on
    RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
</IfModule>

# (4) URL Routing for CMS
<IfModule mod_rewrite.c>

    RewriteCond %{HTTPS} =on
    RewriteRule ^ - [env=proto:https]
    RewriteCond %{HTTPS} !=on
    RewriteRule ^ - [env=proto:http]

    ## Check if file/directory exists
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    ## Route all other URLs to index.php/URL
    RewriteRule ^(.*)$ index.php?url=$1 [PT,L,QSA]
</IfModule>

答案1

你有兩個主要問題......

  1. 您的指令在文件中的順序錯誤.htaccess。您的 HTTP 到 HTTPS 和www規範重新導向需要進行將 URL 路由到 CMS 的前端控制器。因此,錯誤的外部重定向到/index.php?url=courses/acme-course.php- 暴露了您的內部 CMS URL 結構。
  1. 刪除.php其實不是按照您的.htaccess指示執行的?我認為這一定是由您的應用程式/CMS 邏輯完成的?因此,這將總是導致第二次重新導向(因為.htaccess重新導向到相同 URL 路徑上的 HTTPS)。您需要在檔案頂部執行類似以下操作.htaccess來刪除.php副檔名。

    RewriteRule (.+)\.php$ https://www.example.com/$1 [R=301,L]
    

更新:如果我重新排序規則/條件,我的選項 +FollowSymlinks 的位置是否保持不變?

這並不重要在哪裡Options指令發生。然而,將其放在頂部附近是合乎邏輯的(從可讀性的角度來看)。 (Apache 指令不一定會按照它們在設定檔中出現的順序執行,因為每個模組都是獨立工作的。)

假設您正在對文件進行手動編碼,.htaccess那麼它可以被整理...

  1. 不需要(多個)<IfModule mod_rewrite.c>包裝器。 mod_rewrite 是可選的嗎?您的網站是否已移植到多個未啟用 mod_rewrite 的伺服器?

  2. 不需要多個RewriteEngine指令。這最後的實際上實例獲勝並控制整個文件。

    多個<IfModule>區塊RewriteEngine是由程式碼自動編輯和/或設計為在多個伺服器上未經編輯地運行的典型系統。

因此,您的.htaccess文件應該按以下順序重寫:

Options +FollowSymlinks

# Enable the rewrite engine...   
RewriteEngine On

# ----------------------------------------------------------------------
# | Forcing `https://`                                                       |
# ----------------------------------------------------------------------

# Redirect to HTTPS on the "same host" (requirement for HSTS)
RewriteCond %{HTTPS} !=on
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]


# ----------------------------------------------------------------------
# | Forcing `www`                                                          |
# ----------------------------------------------------------------------

RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{SERVER_ADDR} !=127.0.0.1
RewriteCond %{SERVER_ADDR} !=::1
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# ----------------------------------------------------------------------
# | URL Routing for CMS                                              |
# ----------------------------------------------------------------------

# (3)
RewriteCond %{HTTPS} =on
RewriteRule ^ - [env=proto:https]
RewriteCond %{HTTPS} !=on
RewriteRule ^ - [env=proto:http]
   
# (4) - Check if physical file exists
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d  

# (5) - Rewrite all other URLs to index.php/URL
RewriteRule (.*) index.php?url=$1 [L,QSA]

補充筆記:

  • 環境PROTO變數包含所請求的任何協定。按照重定向的順序,現在總是 HTTPS。設定此變數的根本原因是,如果存取 HTTP,CMS 可以重定向到 HTTP;如果存取 HTTPS,則 CMS 可以重定向到 HTTPS。如果您強制使用 HTTPS,那麼它實際上並不適用。 (儘管您的應用程式可能仍會使用此環境變數。)

  • 您很少應該NC在否定條件下使用該標誌。這就是為什麼我將其從條件中刪除!^www\.。您希望它在主機不以www.- 全部小寫開頭時重定向。使用該NC標誌,它將無法重定向WwW.- 儘管這種情況非常罕見。

  • 我已經刪除了 www 規範重新導向上不必要的 HTTPS 檢查。

  • PT最後的標誌在RewriteRule中不是必需的.htaccess。這.htaccess是預設行為(通過)。

  • 在測試之前,您需要清除瀏覽器緩存,因為錯誤的 301 重定向可能已被瀏覽器快取。因此,最好使用 302(臨時)重定向進行測試。

相關內容