У меня на моем виртуальном хосте для 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 заботится о перенаправлении, а второй набор RewriteRule заботится о нормальной обработке страницы.
Без первого набора правил все запросы корректно загружаются под виртуальным хостом SSL.
С первым набором правил перенаправления работают нормально, если они не соответствуют перечисленным ресурсам. например. запрос на
https://example.com/about
перенаправляет на
http://example.com/about
Но при запросе страниц регистрации, входа, приветствия и благодарности возникает проблема. Эти запросы также перенаправляются на сайт без SSL, но некорректно. Запрос на
https://example.com/signup
перенаправляет на
http://example.com/index.php?q=signup
Казалось бы, первый набор правил не соответствует (как и следовало ожидать), затем после обработки второго набора правил первый набор правил применяется снова (не ожидается).
Я не могу сопоставить это неожиданное поведение с какой-либо задокументированной функцией.
Любые идеи?
редактировать
Я нашел в документации несколько неясных ссылок на повторный запуск правил apache, когда соответствие правил происходит в «контексте каталога», однако ссылка была на .htaccess. Моя перезапись выполняется внутри тега <Directory> в моем теге <VirtualHost>. В настоящее время я тестирую перемещение перезаписи за пределы контекста <Directory> - это определенно меняет поведение, но я еще не заставил его работать так, как мне нужно.
Edit2
Проблема, безусловно, вызвана тем, что apache перезапускает обработку перезаписи, когда обработка правила существует в контексте каталога. Я переместил обработку правил за пределы тега <Directory>. Однако теперь строки RewriteCond не работают ... например.
RewriteCond %{REQUEST_FILENAME} -f
поскольку apache еще не разрешил запрошенный ресурс для сопоставления файлов с помощью DocumentRoot. Какой беспорядок.
Итак, я вручную добавляю значение, указанное в DocumentRoot, к RewriteCond. Однако это похоже на плохой взлом. например.
RewriteCond /var/www/example.com/public%{REQUEST_FILENAME} -f
Итак, теперь я ищу способ предотвратить перезапуск apache процесса перезаписи в контексте каталога или, что еще лучше, лучший способ указать необходимые RewriteConds на уровне <VirtualHost>.
Я предлагаю добавить в вашу конфигурацию следующее, что даст вам подробный журнал того, что делает mod_rewrite и почему. Это может помочь понять, почему у вас такое поведение:
RewriteLog /tmp/rewrite.log RewriteLogLevel 9
Как только вы закончите анализировать это, не забудьте удалить эти строки, поскольку они влияют на производительность.
Я остановился на следующем решении, помещая перезаписи вне каких-либо разделов <Directory ...>. Это позволяет мне перенаправлять любой запрос, который не должен быть SSL, на сайт без SSL, и в то же время разрешать обслуживание любого статического контента через SSL (изображения, CSS, js и т. Д.).
<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>