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

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

RewriteRule我正在尝试通过组合一些我之前成功实现的规则来设置通配符子域.htaccess,相信我可以对我的 Apache vhosts 文件使用相同的规则。

本质上,example.com转到www.example.com根路径并查找index.php。根级别的所有其他(动态)子域请求(例如abc.example.com)都会重写(对浏览器不可见)为example.com/process.php?p=abc

其次,任何来自基础/根级别之外的子域的文件请求都需要重写,以便从没有子域的标准域的根路径获取。因此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>

我已成功将不同域的根目录重定向到example.com使用此.htaccess文件,该文件合并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]

并且在这个.htaccess测试中我还成功将子域作为变量重定向到process.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接收是一个空变量,而不是预期的子域作为字符串(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代码中,我发现查询字符串仍在附加,但页面中%2未收到。我可能错误地认为,尽管按照我的代码说明,url 不会将变量显示在浏览器的 url 中,但内部 url 仍会传递它们。尽管如此,我意识到仍然可以使用in将子域确定为字符串,并将其用作页面上的变量,方式与我最初的想法类似。GETprocess.phpp=abcprocess.php$_SERVER['HTTP_X_FORWARDED_HOST']PHP

答案1

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,所以这个指令总是计算为真。

我会将其重写为:

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

我已经做了第一个团体非捕获即(?:www\.)-?:使其非捕获。因此,我们只会获取%1实际的子域。此外,无需在字符类中转义点(以匹配文字点)。这里NC的标志RewriteRule是多余的。

我还删除了RewriteRule 代换因为您已经在指令中指定了 URL 路径RewriteBase

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

其次,任何来自基础/根级别之外的子域的文件请求都需要重写为从没有子域的标准域的根路径获取。因此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 文件一样不加改变地通过。

相关内容