
私のスタック:
- ランプ
- アパッチ/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 つあります。
- ファイル内のディレクティブの順序が間違っています
.htaccess
。HTTPからHTTPSへのリダイレクトとwww
正規のリダイレクトは前にURL を CMS にルーティングするフロント コントローラー。そのため、外部リダイレクトが誤っており/index.php?url=courses/acme-course.php
、内部 CMS URL 構造が公開されます。
の削除は
.php
実際にはあなたのディレクティブによって実行されていないのですか.htaccess
?これはあなたのアプリケーション/CMSロジックによって行われているはずです。したがって、これはいつも2 回目のリダイレクトが発生します (同じ URL パスで HTTPS にリダイレクトされるため)。拡張子を削除するには、ファイル.htaccess
の先頭で次のような操作を行う必要があります。.htaccess
.php
RewriteRule (.+)\.php$ https://www.example.com/$1 [R=301,L]
アップデート:ルール/条件の順序を変更した場合、Options +FollowSymlinks の配置は同じままですか?
それはあまり重要ではないどこディレクティブOptions
が発生します。ただし、読みやすさの観点から、ディレクティブを先頭近くに配置するのが論理的です。(Apache ディレクティブは、各モジュールが独立して動作するため、構成ファイルに表示される順序で必ずしも実行されるわけではありません。)
ファイルを手動でコーディングしている場合.htaccess
は、整理することができます...
(複数の) ラッパーは必要ありません
<IfModule mod_rewrite.c>
。mod_rewrite はオプションですか? サイトは、mod_rewrite が有効になっていない複数のサーバーに移植されますか?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 (一時的) リダイレクトでテストすることをお勧めします。