将htaccess重写规则转换为Apache2虚拟主机规则

我试图通过结合一些.htaccess规则来设置通配符子域RewriteRule ,因为我相信我可以对我的Apache vhosts文件使用相同的规则。

实质上, example.comwww.example.com转到根path并查找index.php 。 所有其他(dynamic)子级别的请求,例如abc.example.com被重写(浏览器不可见)到example.com/process.php?p=abc

其次,基本/根级别之外的任何来自子域的文件的请求需要被重写为从没有子域的标准域的根path获得。 所以abc.example.com/css/style.css需要来自example.com/css/style.css

这是我的尝试。 我得到一个Apache错误:

您无权访问此服务器上的/index.php。

对于任何子域的尝试,除了www,其预期的工作,以及标准的example.com ,仍然工作正常。

 <VirtualHost *:80> ServerAdmin [email protected] ServerName example.com ServerAlias www.example.com DocumentRoot /var/www/example.com/public_html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost> <VirtualHost *:80> ServerAdmin [email protected] ServerName other.example.com ServerAlias *.example.com DocumentRoot /var/www/example.com/public_html/ <Directory /var/www/example.com/public_html/> Options FollowSymLinks AllowOverride all Require all granted RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC] RewriteCond %{HTTP_HOST} ^(www\.)?([^\.]+)\.example\.com$ [NC] RewriteRule ^$ /process.php?p=%2 [QSA,NC] RewriteCond %{REQUEST_FILENAME} !^$ [NC] RewriteRule ^(.*) http://www.example.com/$1 [P] </Directory> </VirtualHost> 

我build立了这个关系,使用这个.htaccess文件成功地将一个不同的域的根目录redirect到example.com ,该文件合并了process.php ,并将所有其他请求发送到example.com的根目录。

 Options +FollowSymLinks RewriteEngine On RewriteBase / # Check the request isn't an existing file RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^$ http://www.example.com/process.php [P] RewriteCond %{REQUEST_FILENAME} !^$ [NC] RewriteRule ^(.*) http://www.example.com/$1 [P] 

也closures这个.htaccesstesting我运行redirect到一个variables作为一个variablesprocess.php成功,虽然它没有赶上其他文件请求,如上面的CSS示例:

 Options +FollowSymLinks RewriteEngine On RewriteBase / RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC] RewriteCond %{HTTP_HOST} ^(www\.)?([^\.]+)\.example\.com$ [NC] RewriteRule ^$ /process.php?p=%2 [QSA,NC] 

更新1

我已经(似乎)取得了一些成功,使用以下代替我的第二个虚拟主机条目。 如果我使用子域, process.php页面正在输出。 虽然模式匹配似乎工作在这方面,我的实际process.php收到一个空的variables,而不是预期的子域作为一个string(for: process.php?p=%2 ):

 <VirtualHost *:80> ServerAdmin [email protected] ServerName other.example.com ServerAlias *.example.com DocumentRoot /var/www/example.com/public_html <Directory /var/www/example.com/public_html> Options FollowSymLinks AllowOverride all Require all granted RewriteEngine on RewriteBase / RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC] RewriteCond %{HTTP_HOST} ^(www\.)?([^\.]+)\.example\.com$ [NC] RewriteCond %{REQUEST_URI} ^/$ RewriteRule ^$ /process.php?p=%2 [NC,QSA] </Directory> </VirtualHost> 

更新2

我以迂回的方式解决了这个问题,但我不确定这是否是最优雅的方式。

使用上面的更新1代码,我看到任何查询string仍然被追加,但%2没有被GET在我的process.php页面接收。 我可能错误地认为,虽然url不显示url中的p=abcvariables到浏览器,根据我的代码指示,内部url仍然传递给他们。 尽pipe如此,我意识到process.php仍然可以使用PHP $_SERVER['HTTP_X_FORWARDED_HOST']将子域名确定为string,并以类似于我最初的想法的方式将其用作页面上的variables。

 RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC] RewriteCond %{HTTP_HOST} ^(www\.)?([^\.]+)\.example\.com$ [NC] RewriteCond %{REQUEST_URI} ^/$ RewriteRule ^$ /process.php?p=%2 [NC,QSA] 

没有设置%2反向引用,因为这是对最后匹配的 CondPattern( RewriteCond模式)的第二个捕获组的反向引用。 最后匹配的CondPattern是^/$ ,它没有任何捕获的组,所以%2总是空的。

那第三个RewriteCond指令看起来是多余的。 这已经被RewriteRule模式^$ (在每个目录上下文中,目录前缀被删除 – 所以这是正确的)。

第一个RewriteCond指令也看起来是多余的。 任何对www.example.com请求都会被第一个VirtualHost捕获,所以这个VirtualHost中的主机名永远不会是www.example.com ,所以这个指令总是被评估为true。

我会重写这个:

 RewriteCond %{HTTP_HOST} ^(?:www\.)?([^.]+)\.example\.com$ [NC] RewriteRule ^$ process.php?p=%1 [QSA] 

我已经使第一不捕获即。 (?:www\.)?:使其不捕获。 所以,我们只能得到实际子域的%1 。 另外,不需要在字符类中逃避点(以匹配字面点)。 RewriteRule上的NC标志在这里是多余的。

我还删除了RewriteRule replace上的斜杠前缀,因为您已经在RewriteBase指令中指定了URLpath。

这只会重写abc.example.com/ ,即。 对文档根目录的请求。

其次,基本/根级别之外的任何来自子域的文件的请求需要重写为从没有子域的标准域的根path获得。 所以abc.example.com/css/style.css需要来自example.com/css/style.css

由于abc.example.com/example.com/指向文件系统上的相同位置,因此您不需要在此处执行任何操作。 example.com/css/style.css应指向与abc.example.com/css/style.css相同的文件。

那么文档根目录中的其他文件呢? 例如。 abc.example.com/file 。 目前这只是通过不变的CSS文件。