Массовый виртуальный хостинг и переписывание правил, вызывающих рекурсивное внутреннее перенаправление

Я использую vhost_alias для массового виртуального хостинга и имею несколько сайтов, использующих mod_rewrite для управления своими фронт-контроллерами.

Я не думаю, что это конкретная проблема Symfony, но я использую Symfony.

Теперь большинство запросов, которые соответствуют любому правилу перезаписи, заканчиваются бесконечным циклом перенаправления, который вызывает ошибку http 500.

Я проверил файлы журналов, и вот что я нашел:

(3) [perdir /home/user/www/mysite/] strip per-dir prefix: /home/user/www/mysite/app_dev.php -> app_dev.php
(3) [perdir /home/user/www/mysite/] applying pattern '^$' to uri 'app_dev.php'
(3) [perdir /home/user/www/mysite/] strip per-dir prefix: /home/user/www/mysite/app_dev.php -> app_dev.php
(3) [perdir /home/user/www/mysite/] applying pattern '^(.*)$' to uri 'app_dev.php'
(2) [perdir /home/user/www/mysite/] rewrite 'app_dev.php' -> 'web/app_dev.php'
(3) [perdir /home/user/www/mysite/] add per-dir prefix: web/app_dev.php -> /home/user/www/mysite/web/app_dev.php
(1) [perdir /home/user/www/mysite/] internal redirect with /home/user/www/mysite/web/app_dev.php [INTERNAL REDIRECT]
(3) [perdir /home/user/www/mysite/] add path info postfix: /home/user/www/mysite/home -> /home/user/www/mysite/home/user/www/mysite/web/app_dev.php
(3) [perdir /home/user/www/mysite/] strip per-dir prefix: /home/user/www/mysite/home/user/www/mysite/web/app_dev.php -> home/user/www/mysite/web/app_dev.php
(3) [perdir /home/user/www/mysite/] applying pattern '^$' to uri 'home/user/www/mysite/web/app_dev.php'

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

Я попробовал это без конфигурации виртуальных хостов (которая работает нормально) и заметил, что перед внутренним перенаправлением есть новая строка:

(2) [perdir /home/user/www/mysite/] strip document_root prefix: /home/user/www/mysite/web/app_dev.php -> /web/app_dev.php
(1) [perdir /home/user/www/mysite/] internal redirect with /web/app_dev.php [INTERNAL REDIRECT]

После этого перенаправления фактический файл сопоставляется, и нет проблем.

Разве виртуальный document_root не должен быть удален в виртуальной конфигурации, а также в обычной конфигурации?

Я не понимаю, почему корень виртуального документа считается частью URL-адреса во внутреннем перенаправлении. Это кажется неправильным.

Я что-то пропустил?

Вот мой файл.htaccess:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule ^$ web/ [QSA,L]    
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ web/$1 [QSA,L]
</IfModule>

Вот мой конфигурационный файл apache:

# get the server name from the Host: header
UseCanonicalName Off

<VirtualHost *:80>
    LogLevel debug
    RewriteLogLevel 3
    RewriteLog "/var/log/apache2/rewrite.log"

    VirtualDocumentRoot /home/user/www/%1

#DocumentRoot /home/user/www
#RewriteEngine on
#RewriteCond %{HTTP_HOST} ^(.*)\.dev$ [NC]
#RewriteRule ^/(.+)$ /home/user/www/%1/$1 [QSA,L]

    <Directory />
        Options FollowSymLinks
        AllowOverride None
    </Directory>
    <Directory /home/user/www>
        Options Indexes FollowSymLinks -MultiViews
        AllowOverride All
        Order allow,deny
        allow from all
    </Directory>

    ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
    <Directory "/usr/lib/cgi-bin">
        AllowOverride None
        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
        Order allow,deny
        Allow from all
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log

    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn

    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Ниже объявления VirtualDocumentRoot есть некоторые закомментированные правила перезаписи.

Это была попытка заменить VirtualDocumentRoot правилами перезаписи, но у него была похожая проблема: полосатым document_root был / home / user / www, оставив имя хоста как часть URL, поэтому у меня возникла та же рекурсивная проблема.

Поэтому я хотел бы знать, кто-нибудь когда-нибудь заставлял mod_vhost_alias работать с mod_rewrite. Я действительно пытался искать везде (даже в Google!), Но не смог найти много информации об этом.

2 ответа

Решение

В качестве цели правила перезаписи (2-й параметр) может использоваться путь к файлу или URL-путь. Когда неясно, что это, mod_rewrite угадывает, и, похоже, он догадывается, что это путь к файлу. Несколько вещей, которые вы можете попробовать:

  1. Добавьте базу перезаписи или сделайте цель абсолютным URL-путем, добавив ведущий /
  2. Добавьте дополнительное условие, чтобы проверить, начинается ли URI с /web/
  3. Возможно, добавьте еще одно условие, чтобы проверить, существует ли цель

Для 1 и 2:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule ^$ /web/ [QSA,L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !^/web/
    RewriteRule ^(.*)$ /web/$1 [QSA,L]
</IfModule>

возможно 3:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule ^$ /web/ [QSA,L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{DOCUMENT_ROOT}/web%{REQUEST_URI} -f [OR]
    RewriteCond %{DOCUMENT_ROOT}/web%{REQUEST_URI} -d
    RewriteRule ^(.*)$ /web/$1 [QSA,L]
</IfModule>

Чтобы включить модуль перезаписи, запустите "apache2 enable module rewrite":

sudo a2enmod rewrite

Вам необходимо перезапустить веб-сервер, чтобы применить изменения:

sudo service apache2 restart

VirtualHost должен выглядеть следующим образом: ServerName localhost.myproject.dev ServerAdmin webmaster@localhost

DocumentRoot /var/www/project_path
<Directory /var/www/project_path>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride None
    Order allow,deny
    allow from all
    <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule ^(.*)$ /app.php [QSA,L]
    </IfModule>
</Directory>

Другие вопросы по тегам