Apache vhost:别名和RewriteRule

Apache vhost: Alias and RewriteRule

我有一个 URL(域),用于多个目录(项目)。将 .htaccess 放入其中时,我的行为非常奇怪。

虚拟主机:

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

而且效果很好。当我继续 sub.mywebsite.com/ 时,它到达了 /foo/bar/things 目录,反之亦然。


现在,让我们在 /srv/www/new 中添加一个简单的 .htaccess :

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

所以当我继续 sub.mywebsite.com/pro/hello/ 时,调用的文件应该是带有 GET arg 的 /srv/www/new/php/file.php。我仔细检查过,规则是好的。

这里是 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]

然后 online htaccess checker 确认:The new url is http://sub.mywebsite.com/php/file.php%3Ftext=testing

但是我找不到 apache 404:

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

是的,ls -l /srv/www/new/php/file.php 该文件存在。

非常奇怪的部分是:在 apache 错误日志中,我有:

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

问题:

  1. 那是什么鬼东西?为什么 error_log 中的文件不一样 作为我的浏览器上显示的那个?
  2. 为什么 apache 不能像 .htaccess 要求的那样加载正确的文件 /srv/www/new/php/file.php

如果需要,请随时向我询问更多数据。我想明白!

注意:/foo/bar/things 中没有 .htaccess;我在虚拟主机中尝试了很多东西,比如添加 <directory>

您的两个问题的答案都已显示在您的屏幕和日志中:

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

要求URL.

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

文件不存在。

因此,apache 不会尝试获取位于文件系统 /srv/www/new/php/ 文件夹中的文件 file.php。它正在尝试打开 URL http://sub.mywebsite.com/srv/www/new/php/file.php,这解释了浏览器错误和错误日志中的行,因为对于 URL 它确实应该查看 /foo/bar/things/srv/www/new/php/file.php.

来自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.

解决方案:将 RewriteBase "/pro" 添加到您的 .htaccess

可以在Rewrite Log中看到区别:

没有 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]

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]

Apache 更新 > 2.4.16

从版本 2.4.16 开始,当通过 Alias:

映射请求时,不需要 RewriteBase 指令

This directive is required when you use a relative path in a substitution in per-directory (htaccess) context unless any of the following conditions are true:

  • The original request, and the substitution, are underneath the [DocumentRoot](https://httpd.apache.org/docs/current/mod/core.html#documentroot) (as opposed to reachable by other means, such as [Alias](https://httpd.apache.org/docs/current/mod/mod_alias.html#alias)).
  • The filesystem path to the directory containing the [RewriteRule](https://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriterule), suffixed by the relative substitution is also valid as a URL path on the server (this is rare).
  • In Apache HTTP Server 2.4.16 and later, this directive may be omitted when the request is mapped via [Alias](https://httpd.apache.org/docs/current/mod/mod_alias.html#alias) or [mod_userdir](https://httpd.apache.org/docs/current/mod/mod_userdir.html).

所以基本上您不会再收到任何 AH00128: File does not exist: 错误。

值得注意的是,CentOS 7.x 随附带有安全补丁的 Apache 2.4.6:至于 2022/01/07,您将获得修复了 CVE-2021-40438 的 2.4.6-97.2。所以如果你想管理多个别名你需要用不同的包升级,但这是另一回事...