
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>