Apache が「ディレクトリ コンテキスト」内で書き換え処理を再開しないようにする方法

Apache が「ディレクトリ コンテキスト」内で書き換え処理を再開しないようにする方法

SSL 接続用の仮想ホストには次の内容が含まれています (非 SSL 仮想ホストは同じに見えますが、リダイレクト用の最初のルール セットがありません)。

DocumentRoot /var/www/example.com/public/
<Directory "/var/www/example.com/public/">
  #only mod_rewrite configuration is shown here

  RewriteEngine on
  RewriteBase /

  RewriteCond $1 !=signup
  RewriteCond $1 !=login
  RewriteCond $1 !=welcome
  RewriteCond $1 !=thankyou
  RewriteRule ^(.*)$ http://example.com/$1 [L,R,QSA]

  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^(.+)$ index.php?q=$1 [L,QSA]
</Directory>

私の意図は、一致しないページ リクエスト (signup|login|welcome|thankyou) をそれ以上処理せずに非 SSL 仮想ホストにリダイレクトし、それ以外の場合はリダイレクトせずに SSL 仮想ホスト内でリクエストを処理することです。

最初の RewriteRule セットはリダイレクトを処理し、2 番目の RewriteRule セットは通常のページ処理を処理します。

最初のルールセットがない場合、すべてのリクエストは SSL 仮想ホストで正しく読み込まれます。

最初のルールセットでは、リストされたリソースに一致しないリダイレクトは正常に機能します。例:

https://example.com/about

リダイレクト先

http://example.com/about

しかし、サインアップ、ログイン、ウェルカム、サンキューページをリクエストすると問題が発生します。これらのリクエストも非SSLサイトにリダイレクトされますが、その方法は不完全です。

https://example.com/signup

リダイレクト先

http://example.com/index.php?q=signup

最初のルール セットは一致しないようです (予想どおり)。その後、2 番目のルール セットが処理された後、最初のルール セットが再度適用されます (予想外です)。

この予期しない動作を、文書化された機能と一致させることはできません。

何か案は?

編集

ドキュメントの中に、ルールの一致が「ディレクトリ コンテキスト」内で発生したときに Apache がルールを再実行するという不明瞭な参照がいくつか見つかりましたが、その参照は .htaccess に関するものでした。書き換えは、<VirtualHost> タグ内の <Directory> タグ内で発生しています。現在、書き換えを <Directory> コンテキスト外に移動することをテストしています。これにより動作が確実に変更されるようですが、まだ必要な動作には至っていません。

編集2

この問題は、ルール処理がディレクトリ コンテキスト内に存在する場合に Apache が書き換え処理を再開することによって確実に発生します。ルール処理を <Directory> タグの外側に移動しました。ただし、RewriteCond 行が機能しなくなりました... 例:

RewriteCond %{REQUEST_FILENAME} -f

Apache がまだ DocumentRoot を使用して要求されたリソースをファイル マッピングに解決していないためです。これはひどい状況です。

そこで、DocumentRoot で指定した値を RewriteCond の先頭に手動で追加します。ただし、これは貧弱なハックのようです。例:

RewriteCond /var/www/example.com/public%{REQUEST_FILENAME} -f

そこで、現在、ディレクトリ コンテキスト内で Apache が書き換えプロセスを再開しないようにする方法、または次善策として、<VirtualHost> レベルで必要な RewriteConds を指定するより良い方法を探しています。

答え1

設定に次の内容を追加することをお勧めします。これにより、mod_rewrite が何を実行しているか、またその理由についての詳細なログが提供されます。これにより、このような動作が発生する理由が明らかになる場合があります。

RewriteLog /tmp/rewrite.log
RewriteLogLevel 9

分析が完了したら、これらの行はパフォーマンスに影響するため、必ず削除してください。

答え2

私は、書き換えを <Directory ...> セクションの外側に配置するという次の解決策に落ち着きました。これにより、SSL ではないリクエストを非 SSL サイトにリダイレクトできると同時に、静的コンテンツ (画像、CSS、JS など) を SSL 経由で提供できるようになります。

<VirtualHost ...>
  ...
  RewriteEngine on

  RewriteCond $1 !=signup
  RewriteCond $1 !=login
  RewriteCond $1 !=welcome
  RewriteCond $1 !=thankyou
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
  RewriteRule ^/(.*)$ http://example.com/$1 [R=303,QSA,L]

  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteCond %{REQUEST_URI} !=/robots.txt
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
  RewriteRule ^/(.+)$ /index.php?q=$1 [QSA,L]
  ...
</VirtualHost>

関連情報