Как запретить 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>

Моя цель — перенаправить любой несоответствующий запрос страницы (регистрация|вход|приветствие|спасибо) на виртуальный хост без 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> - это, конечно, похоже, меняет поведение, но я пока не заставил это работать так, как мне нужно.

Редактировать2

Проблема, безусловно, вызвана тем, что Apache перезапускает обработку перезаписи, когда обработка правила существует в контексте каталога. Я переместил обработку правила за пределы тега <Directory>. Однако теперь строки RewriteCond не работают... например.

RewriteCond %{REQUEST_FILENAME} -f

потому что apache еще не разрешил запрошенный ресурс для сопоставления файла с помощью DocumentRoot. Какой беспорядок.

Итак, я затем вручную добавляю значение, которое я указал в DocumentRoot, к RewriteCond. Однако это кажется плохим хаком. Например.

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

Итак, теперь я ищу способ запретить Apache перезапускать процесс перезаписи в контексте каталога или, что еще лучше, лучший способ указать необходимые RewriteConds на уровне <VirtualHost>.

решение1

Предлагаю добавить следующее в вашу конфигурацию, что даст вам подробный лог того, что делает mod_rewrite и почему. Это может помочь прояснить, почему у вас такое поведение:

RewriteLog /tmp/rewrite.log
RewriteLogLevel 9

После того как вы закончите анализ, обязательно удалите эти строки, так как они влияют на производительность.

решение2

Я остановился на следующем решении, разместив перезаписи вне разделов <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>

Связанный контент