.htaccess のリダイレクトが機能しないのはなぜですか?

.htaccess のリダイレクトが機能しないのはなぜですか?

私はWordpressのウェブサイトを持っています。.phpのURLを.phpサフィックスのないURLにリダイレクトしたいです。.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ウェブページは正常に表示されます。なぜでしょうか?

答え1

なぜなら、リダイレクトは無条件再びリダイレクトすることになりますURL がindex.php(WordPress フロント コントローラー) に書き換えられました。

リクエストする場合/somepage.php

  1. 最初のルールによってリダイレクトされます/somepage。リダイレクト応答がクライアントに返されます。
  2. 2回目のリクエストでは、最後のルールによって/somepage内部的に書き換えられます/index.php。書き換えエンジンはその後、(ディレクトリコンテクスト)...
  3. /index.phpリダイレクト先(最初のルールによって)にリダイレクトされます/index。リダイレクト応答がクライアントに返されます。
  4. 3 番目のリクエストは、最後の書き換えによって/index内部的に書き換えられます/index.php。その後、書き換えエンジンが最初からやり直します...
  5. 3 に進みます (無限リダイレクト ループに陥ります)。

ディレクトリコンテキスト ( など.htaccess) では、書き換えエンジンはスクリプトを 1 回だけ通過させるのではなく、URL が変更されずに通過するまでループします。 ( ENDApache 2.4 で フラグを使用した場合、または外部 3xx リダイレクトが発生しない限り)。

を remove に変更すると、.htmlに書き換えますが/index.php、これは で終わっていない.htmlため、リダイレクト ディレクティブ ( を削除する.html) は一致しないため、正常に動作します。

これを解決するには、書き換えられたリクエストのリダイレクトを避ける必要があります。これは、次のいずれかの方法で実行できます。

  • 最後の書き換え時に フラグ (Apache 2.4+)を使用するEND代わりに、L書き換えエンジンのそれ以上のループを防止します。ただし、標準の WordPress ディレクティブ (下記参照) の変更は避けるべきなので、これは推奨されるオプションではない可能性があります。これは Apache 2.2 でも機能しません。

  • または、サーバー変数 (HTTP 要求ヘッダーの最初の行を含み、要求が書き換えられても変更されない).phpに対して拡張子を確認しますTHE_REQUEST。例:

    # 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自体がこれを維持しようとし、後でこのコードを上書きする可能性があるため、セクション内のコードを編集しないでください。このルールは前にコメントマーカー。ファイルの後半 (WordPress セクション) に表示されるディレクティブ# BEGIN WordPressを繰り返す必要はありません。RewriteEngine On

誤った (永続的な) リダイレクトはブラウザによってキャッシュされている可能性が高いため、テストする前にブラウザのキャッシュをクリアする必要があります。キャッシュの問題を回避するために、最初に 301 (一時的な) リダイレクトでテストしてください。

.phpただし、これだけでは拡張子のないファイルにアクセスすることはできません.php。拡張子のない URL は、内部的にファイルに書き換えられる必要があるためです.php

関連情報