Apache(httpd)VirtualHost RewriteCond 变量不起作用

Apache(httpd)VirtualHost RewriteCond 变量不起作用

我正在尝试创建一个动态虚拟主机条目,目的是将所有流量重定向到.mydomain.com 到 /var/www/html/ 这部分有效,但我还要检查重写条件,检查目录是否存在,如果不存在,那么我想将所有流量重定向到根 /var/www/html/index.php。

这部分不起作用,因为在我测试期间我注意到没有一个重写变量起作用,它们都是空白的,我无法弄清楚为什么这是我的虚拟主机配置

# get the server name from the Host: header
UseCanonicalName Off

# this log format can be split per-virtual-host based on the first field
# LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
LogFormat "%{Host}i %h %l %u %t \"%r\" %s %b" vcommon
CustomLog logs/access_log vcommon

<VirtualHost *:80>
    ServerName mydomain.com
    ServerAlias www.mydomain.com
    VirtualDocumentRoot /var/www/html
</VirtualHost>

<VirtualHost *:80>
    ServerName vhosts.mydomain.com
    ServerAlias *
    VirtualDocumentRoot /var/www/html/%1

    RewriteEngine on
    LogLevel warn rewrite:trace4

    # If the request is not for a valid directory
    RewriteCond /var/www/html/%1 !-d
    RewriteCond %{REQUEST_FILENAME} !-d
    # If the request is not for a valid file
    RewriteCond %{REQUEST_FILENAME} !-f
    # If the request is not for a valid link
    RewriteCond %{REQUEST_FILENAME} !-l

    RewriteRule .* /var/www/html/index.php

</VirtualHost>

你会注意到,我在测试和查看日志文件时可以使用变量的几种用法

[Wed Jul 29 16:56:56.015818 2015] [rewrite:trace2] [pid 23898] mod_rewrite.c(475): [client xx.xx.xx.xx:4863] xx.xx.xx.xx - - [fake.mydomain.com/sid#7f5c89bcf570][rid#7f5c89ed5000/initial] init rewrite engine with requested uri /
[Wed Jul 29 16:56:56.016050 2015] [rewrite:trace3] [pid 23898] mod_rewrite.c(475): [client xx.xx.xx.xx:4863] xx.xx.xx.xx - - [fake.mydomain.com/sid#7f5c89bcf570][rid#7f5c89ed5000/initial] applying pattern '.*' to uri '/'
[Wed Jul 29 16:56:56.018361 2015] [rewrite:trace4] [pid 23898] mod_rewrite.c(475): [client xx.xx.xx.xx:4863] xx.xx.xx.xx - - [fake.mydomain.com/sid#7f5c89bcf570][rid#7f5c89ed5000/initial] RewriteCond: input='/var/www/html/' pattern='!-d' => not-matched
[Wed Jul 29 16:56:56.018411 2015] [rewrite:trace1] [pid 23898] mod_rewrite.c(475): [client xx.xx.xx.xx:4863] xx.xx.xx.xx - - [fake.mydomain.com/sid#7f5c89bcf570][rid#7f5c89ed5000/initial] pass through /

尽管 %1 很好地通过了虚拟目录,但它在 mod 重写规则中不起作用。变量的所有其他用途都产生相同的结果,任何帮助都将不胜感激。

不确定是否有区别,但这是在 Amazon Linux 构建的 AWS 中运行的。

答案1

%1 不是整个 Apache 配置的一种全局变量。

虚拟文档根它对应于“主机”名称的第一部分,并且在RewriteCond或中RewriteRule它表示对捕获组的反向引用 RewriteCond. 请参阅 Apache 文档重写条件

扔掉那部分:

RewriteCond /var/www/html/%1 !-d

您对 %1 的使用是错误的,您之前没有任何 RewriteCond,因此 %1 是空字符串。因此基本上您有一个条件,即“如果 /var/www/html/ 不是目录,则执行...”

但显然/var/www/html是一个目录,这就是为什么你的日志行说

RewriteCond: input='/var/www/html/' pattern='!-d' => not-matched

更新作为您评论的后续内容:

需要理解的是,Apache 由许多不同的部分组成,这些部分是模块。每个模块都有自己的语法。这使得整体非常强大,但可能会造成混淆,就像您的问题一样。每个模块都可以定义一个语法,其中的变量表示%1每个模块中的其他内容。

可能是我现在更好地理解了你想要做什么:

  1. 检查请求是否有与其子域对应的目录,如果没有,则发送到/var/www/html/nosubdomain.php
  2. 否则,检查请求是否对应于文件/目录/链接,如果不是,则发送到/var/www/html/nofile.php

步骤 1:获取子域名

要获取子域名,可以使用mod_rewrite的功能来定义和设置环境变量(这里%1是RewriteCond中捕获的结果):

# Setting environment variable SUBDOMAIN = (subdomain).example.com

RewriteCond %{HTTP_HOST} ^([^\.]*)\.example\.com$
RewriteRule . - [E=SUBDOMAIN:%1]

步骤 2:现在,您可以在重写规则/条件中使用 SUBDOMAIN 变量,并检查与子域对应的目录是否存在。如果不存在,则重定向到定义的页面

# Test if subdomain directory exists, if not, redirect to a 
# standard page (/var/www/html/nosubdomain.php).

RewriteCond /var/www/html/%{ENV:SUBDOMAIN} !-d
RewriteRule .* /var/www/html/nosubdomain.php [L]

步骤 3:检查请求的文件是否存在,如果不存在,则发送标准页面 ( /var/www/html/nofile.php)。为此,最好依靠 Apache 自身检查并使用 ErrorDocument。我们需要一个别名,因为您希望文件nofile.php位于 VirtualDocumentRoot 之外 ( /var/www/html/subdomain/)

Alias /nofile.php /var/www/html/nofile.php
ErrorDocument 404 /nofile.php

在您的指令之后将所有这些步骤组合在一起,RewriteEngine On您应该会得到一个有效的设置,当然您必须根据具体用例进行调整。我已经测试了这个设置,它按我的要求工作,但在 Apache 2.2 上。

如果您在其他地方不使用 SUBDOMAIN,您也可以将步骤 1 和 2 合并在一起:

RewriteCond %{HTTP_HOST} ^([^\.]*)\.example\.com$
RewriteCond /var/www/html/%1 !-d
RewriteRule .* /var/www/html/nosubdomain.php [L]

相关内容