.HTACCESS が不要な 301 リダイレクト チェーンを作成しています - 削除するにはどうすればいいですか?

.HTACCESS が不要な 301 リダイレクト チェーンを作成しています - 削除するにはどうすればいいですか?

私のスタック:

  • ランプ
  • アパッチ/2.4.41

背景情報:

最近、クライアントのために新しい Web サイトを立ち上げました。再設計のプロセス中に、次のことを決定しました。

  • サイト全体をHTTPSに切り替える
  • URLから.php拡張子を削除します
  • CMSへの切り替え

古い URL の例:
http://www.example.com/courses/acme-course.php

新しい URL の例:
https://www.example.com/courses/acme-course

私の問題:

ユーザーが古い URL のいずれかに移動すると、不要な追加の 301 リダイレクトが発生します。

追加の 301 リダイレクトが作成され、単一の 301 リダイレクトを使用してユーザーを正しい宛先 URL に直接送信しない理由がわかりません。

興味深い観察:

HTTP ではなく HTTPS で古い URL を使用すると、不要な追加の 301 リダイレクトは発生しません。

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

上記の URL を使用すると、次の正しい宛先 URL への単一の 301 リダイレクトが正しく実行されます。https://www.example.com/courses/acme-course

301 リダイレクト チェーンの例を次に示します。

元のリクエスト URL:

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

主な問題は 2 つあります。

  1. ファイル内のディレクティブの順序が間違っています.htaccess。HTTPからHTTPSへのリダイレクトとwww正規のリダイレクトは前にURL を CMS にルーティングするフロント コントローラー。そのため、外部リダイレクトが誤っており/index.php?url=courses/acme-course.php、内部 CMS URL 構造が公開されます。
  1. の削除は.php実際にはあなたのディレクティブによって実行されていないのですか.htaccess?これはあなたのアプリケーション/CMSロジックによって行われているはずです。したがって、これはいつも2 回目のリダイレクトが発生します (同じ URL パスで HTTPS にリダイレクトされるため)。拡張子を削除するには、ファイル.htaccessの先頭で次のような操作を行う必要があります。.htaccess.php

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

アップデート:ルール/条件の順序を変更した場合、Options +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 がアクセスされた場合は HTTPS にリダイレクトできるようにするためです。HTTPS を強制している場合は、実際には適用されません。(ただし、この環境変数はアプリケーションによって引き続き使用される可能性があります。)

  • 否定条件でフラグを使用することはほとんどありませんNC。そのため、条件からフラグを削除しました!^www\.。ホストがwww.すべて小文字の - で始まっていない場合にリダイレクトする必要があります。NCフラグを使用するとリダイレクトに失敗しますWwW.が、いずれにしてもこれは非常にまれです。

  • www 正規リダイレクトでの HTTPS の不要なチェックを削除しました。

  • PT最後のフラグはではRewriteRule必要ありません.htaccess。 では.htaccessこれがデフォルトの動作です (パススルー)。

  • 誤った 301 リダイレクトはブラウザによってキャッシュされている可能性が高いため、テストの前にブラウザのキャッシュをクリアする必要があります。このため、302 (一時的) リダイレクトでテストすることをお勧めします。

関連情報