Search code examples
apache.htaccessunixaliasvirtualhost

Apache vhost: Alias and RewriteRule


I have one URL (domain), for multiple directories (project). And I have a very odd behaviour when putting a .htaccess in it.

  • sub.mywebsite.com/ => /foo/bar/things
  • sub/mywesite.com/pro => /srv/www/new

VirtualHost:

<VirtualHost *:80>
    DocumentRoot /foo/bar/things
    ServerName sub.mywebsite.com
    Alias /pro /srv/www/new
</VirtualHost>

And it works perfectly. When I go on sub.mywebsite.com/ it hit the /foo/bar/things dir and the other way around.


Now, let's add a simple .htaccess in /srv/www/new :

RewriteEngine on
RewriteRule ^(.*)/$    php/file.php?text=$1   [L,QSA]

So when I go on sub.mywebsite.com/pro/hello/ the file called is supposed to be /srv/www/new/php/file.php with a GET arg. I double-checked, the rule is good.

Here is the end of the RewriteLogLevel 4:

192.168.123.123 - - [25/Apr/2018:19:28:11 +0200] [sub.mywebsite.com/sid#7f317dd08b8][rid#7f37eca9f78/initial] (1) 
[perdir /srv/www/new/] internal redirect with /srv/www/new/php/file.php [INTERNAL REDIRECT]

And an online htaccess checker confirm it: The new url is http://sub.mywebsite.com/php/file.php%3Ftext=testing

But I've got an apache 404 not found:

Not Found
The requested URL /srv/www/new/php/file.php was not found on this server.

And yes, ls -l /srv/www/new/php/file.php the file exists.

The VERY ODD part is this: in the apache error log, I've got:

[Wed Apr 25 19:45:30 2018] [error] [client 192.168.123.123] File does not exist: /foo/bar/things/srv

Questions:

  1. What the hell is that? Why the file in the error_log is not the same as the one displayed on my browser?
  2. Why apache can't load the right file /srv/www/new/php/file.php as the .htaccess ask it?

Feel free to ask me more data if needed. I want to understand!

NB: there is no .htaccess in /foo/bar/things ; I've tried a lot of things in my vhost, like adding a <directory>, etc.


Solution

  • The answer to both of your questions is already shown on your screen and in your logs:

    The requested URL /srv/www/new/php/file.php was not found on this server.
    

    The requested URL.

    AH00128: File does not exist: /foo/bar/things/srv/www/new/php/file.php
    

    File does not exist.

    So, apache is not trying to fetch the file file.php which is located in /srv/www/new/php/ folder on your filesystem. It is trying to open URL http://sub.mywebsite.com/srv/www/new/php/file.php, which explains both the browser error and the line in your error log, since for that URL it really should look into /foo/bar/things/srv/www/new/php/file.php.

    From http://httpd.apache.org/docs/current/mod/mod_rewrite.html:

    The rewrite engine may be used in .htaccess files and in sections, with some additional complexity.
    (...)
    See the RewriteBase directive for more information regarding what prefix will be added back to relative substitutions.
    (...)
    The RewriteBase directive specifies the URL prefix to be used for per-directory (htaccess) RewriteRule directives that substitute a relative path. This directive is required when you use a relative path in a substitution in per-directory (htaccess) context.
    (...)
    This misconfiguration would normally cause the server to look for an directory under the document root.

    Solution: add RewriteBase "/pro" to your .htaccess

    You can see the difference in Rewrite Log:

    Without RewriteBase:

    [perdir /srv/www/new/] rewrite 'hello/' -> 'php/file.php?text=hello'
    [perdir /srv/www/new/] add per-dir prefix: php/file.php -> /srv/www/new/php/file.php
    [perdir /srv/www/new/] internal redirect with /srv/www/new/php/file.php [INTERNAL REDIRECT]
    

    With RewriteBase "/pro":

    [perdir /srv/www/new/] rewrite 'hello/' -> 'php/file.php?text=hello'
    [perdir /srv/www/new/] add per-dir prefix: php/file.php -> /srv/www/new/php/file.php
    [perdir /srv/www/new/] trying to replace prefix /srv/www/new/ with /pro
    strip matching prefix: /srv/www/new/php/file.php -> php/file.php
    add subst prefix: php/file.php -> /pro/php/file.php
    [perdir /srv/www/new/] internal redirect with /pro/php/file.php [INTERNAL REDIRECT]