web-dev-qa-db-ja.com

Apacheのmod_rewriteとPHPのREQUEST_URI変数

リクエストされた元のURLではなく、書き直された後、ApacheがPHP $_SERVER['REQUEST_URI']変数にURLを渡す際に問題があります。

WordPress Webサイトがあり、ルートパスではなくサブディレクトリに移動したいが、そのURLをルートURLのままにしておきたいので、この書き換えを行っています。

これは一貫して発生しません。 www.xyz.com/wp-adminをリクエストすると、PHP REQUEST_URI変数にwww.xyz.com/wordpress/wp-admin(書き換えられた後のURL))が入力されますが、www.xyz.com/wp-admin/(末尾にスラッシュを付ける)は、実際にPHP REQUEST_URI変数にwww.xyz.com/wp-admin/(元のURL、書き換え前のURL)を入力します)。 REQUEST_URIには、書き換えられる前にURLが入力されます。

私の.htaccessファイルは以下のとおりです。

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_Host} ^(www.)?xyz.com$
RewriteCond %{REQUEST_URI} !^/wordpress/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /wordpress/$1
RewriteCond %{HTTP_Host} ^(www.)?xyz.com$
RewriteRule ^(/)?$ wordpress/index.php [L]
</IfModule>`

PHPのバージョンは5.3です。 Apacheのバージョンは2.4(Win32)です。


[〜#〜] update [〜#〜]:詳しく調べて、URL www.xyz.com/wp-adminを入力すると、最初にwww.xyz.com/wordpress/wp-admin/への301リダイレクトがありますが、これはwww.xyz.com/wp-admin/(末尾にスラッシュが付いている)では発生しません。末尾にスラッシュがあるものについては、予想どおり、書き換えのみがあります。したがって、問題は、なぜ301リダイレクトがURLに対して末尾のスラッシュなしで最初に発生するのかということです。

明確にするために、実際のフォルダー/wp-admin/はありませんが、フォルダー/wordpress/wp-admin/があります。

4
Mg512

「問題」はmod_dirに関連しています(ただし、mod_dirは厳密には「問題」ではありません。正しいことを実行し、URLを「修正」しています)。

wp-adminは物理ディレクトリであるため、mod_dirは末尾にスラッシュを追加してURLを「修正」します(ディレクトリインデックスを正しく提供するために必要です。例:index.php)。これは、301リダイレクトで行われます。問題は、これが発生しているということですafter内部の書き換えにより、書き換えがリダイレクトになり、/wordpressサブディレクトリが公開されます。

したがって、正しいURLは厳密に/wp-admin/です(末尾にスラッシュが付きます)。 /wordpressサブディレクトリがなく、すべてがドキュメントルートにある場合、mod_dirは/wp-admin/wp-admin/にリダイレクトするだけで、/wp-admin/index.phpが提供されます(内部サブリクエストとして)。

あなたがする必要があるのは、末尾のスラッシュを手動で追加することです。要求されたURLがスラッシュで終わっていないが、それ以外の場合は/wordpressサブディレクトリ内の物理ディレクトリにマップされる場合は、末尾のスラッシュを(外部リダイレクトを介して)追加します。このリダイレクトは発生するはずです内部の書き換え。

したがって、次のbeforeを試して、既存のディレクティブを確認してください。

# Append a slash if it is omitted and would map to a directory
RewriteCond %{REQUEST_URI} !^/wordpress/
RewriteCond %{REQUEST_URI} !/$
RewriteCond %{DOCUMENT_ROOT}/wordpress/$1 -d
RewriteRule (.*) /$1/ [R=302,L]

これが行うことは、/wordpress/をまだ開始していない要求の場合およびはスラッシュで終了せず、/wordpressサブディレクトリ内の物理ディレクトリにマップしてからリダイレクトし、スラッシュを追加します。したがって、/wp-adminのリクエストは、/wp-admin/がディレクトリとして存在する場合、/wordpress/wp-adminにリダイレクトされます。 (内部の書き換えは、以前と同じようにURLをルーティングします。)

以前の301リダイレクト(mod_dirによる)がキャッシュされているため、ブラウザーのキャッシュがクリアされていることを確認する(またはブラウザーのオブジェクトインスペクターを開いてキャッシュを無効にしてテストする)必要があります。

正常に機能していることが確認できたら、302(一時的)リダイレクトを301(永続的)に変更します(意図する場合)。 302はブラウザによってキャッシュされるため、テストが少し簡単になります。


余談:

... ApacheがPHP $_SERVER['REQUEST_URI']変数に、元のURLが要求された後ではなく、書き換えられた後にURLを渡します。

Apacheは、実際にはREQUEST_URI変数をmod_rewriteからPHPに直接渡しません。これら2つの変数は同じ名前ですが、私が知る限り、PHP自体が、リクエストからこの変数を設定します。

Apache REQUEST_URIサーバー変数とPHPの$_SERVER['REQUEST_URI']スーパーグローバルには、実際には異なる情報が含まれています。

  • PHPの$_SERVER['REQUEST_URI']にはクエリ文字列が含まれていますが、ApacheのREQUEST_URIサーバー変数には含まれていません。
  • PHPの$_SERVER['REQUEST_URI']には、書き換えられたURLではなく、リクエストからの元のURLパスが含まれています。一方、ApacheのREQUEST_URIサーバー変数は(リクエスト全体で)更新され、書き換えられたURLが含まれます。
1
MrWhite