.HTACCESSは不必要な301リダイレクトチェーンを作成しています-削除する方法は?

Jan 12 2020

私のスタック:

  • ランプ
  • Apache / 2.4.41

背景情報:

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

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

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

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

私の問題:

ユーザーが古いURLの1つに移動すると、不要な追加の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>

回答

MrWhite Jan 12 2020 at 02:19

あなたには2つの主要な問題があります。

  1. .htaccessファイル内のディレクティブの順序が間違っています。HTTPからHTTPSおよびwww正規リダイレクトは、URLをCMSにルーティングするフロントコントローラーのに移動する必要があります。したがって、への誤った外部リダイレクト/index.php?url=courses/acme-course.php-内部CMSURL構造を公開します。
  1. の削除.phpは、実際には.htaccessディレクティブによって実行されていませんか?!これはアプリケーション/ CMSロジックによって行われている必要があると思いますか?その結果、これは常に2番目のリダイレクトになります(.htaccess同じURLパスでHTTPSにリダイレクトするため)。拡張子.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を強制している場合、実際には適用されません。(ただし、このenv varは引き続きアプリケーションで使用される場合があります。)

  • NC否定された状態でフラ​​グを使用することはめったにありません。したがって、なぜ私はそれを条件から削除したのですか!^www\.。ホストがwww.-すべて小文字で始まらないときにリダイレクトする必要があります。NCフラグはリダイレクトに失敗しますWwW.-これは非常にまれとにかくだろうが。

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

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

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