apache.htaccesssymfonymod-rewritemod-vhost-alias

Mass virtual hosting and rewrite rules causing recursive internal redirect


I'm using vhost_alias for to do mass virtual hosting and have several sites using mod_rewrite to manage their front controllers.

I don't think this is a specific Symfony issue, but I'm using Symfony.

Now most requests that match any rewrite rule end up in an infnite redirect loop that causes an HTTP error 500.

I checked the log files and this is what I found:

(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'

As you can see, after the internal redirect line, the absolute path becomes part of the URI being matched, this URI of course does not match any files and is processed again as a completely new URI, this results in a new absolute path appended at the URI. This process repeats itself until reaching the configured limit.

I tried this without the virtual hosts configuration (which works fine) and noticed that before the internal redirect there is a new line:

(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]

After this redirect the actual file is matched and there is no problem.

Shouldn't the virtual document_root be stripped in the virtual configuration as well as in the regular configuration?

I don't understand why the virtual document root is considered part of the URI in the internal redirect. This seems to be plain wrong.

Am I missing some configuration option?

Here is my .htaccess file:

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

Here is my apache config file:

# 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>

Below the VirtualDocumentRoot declaration there are some commented out rewrite rules.

That was an attempt at replacing the VirtualDocumentRoot with rewrite rules, but it had a similar problem: the document_root being striped was /home/user/www, leaving the hostname as part of the URL, so I end up having the same recursive problem.

So I would like to know if someone has ever made mod_vhost_alias work with mod_rewrite. I really tried to search everywhere (even google!) but could not find much information about this.


Solution

  • There target of a rewrite rule (the 2nd parameter) can either be a file-path or a URL-path. When it's not clear what it is, mod_rewrite guesses, and it looks like it may be guessing that it's a file-path. A few things you can try:

    1. Add a rewrite base or make the target an absolute URL-path by adding a leading /
    2. Add an extra condition to check if the URI starts with /web/
    3. Maybe, add another condition to check if the target exists

    For 1 and 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>
    

    possibly 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>