我的虚拟主机中有以下用于 SSL 连接的内容(我的非 ssl 虚拟主机看起来相同,但没有第一个用于重定向的规则集)。
DocumentRoot /var/www/example.com/public/
<Directory "/var/www/example.com/public/">
#only mod_rewrite configuration is shown here
RewriteEngine on
RewriteBase /
RewriteCond $1 !=signup
RewriteCond $1 !=login
RewriteCond $1 !=welcome
RewriteCond $1 !=thankyou
RewriteRule ^(.*)$ http://example.com/$1 [L,R,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^(.+)$ index.php?q=$1 [L,QSA]
</Directory>
我的意图是让任何不匹配的页面请求 (signup|login|welcome|thankyou) 被重定向到非 ssl 虚拟主机而不进行进一步处理,否则不重定向,而是在 SSL 虚拟主机内处理请求。
第一个 RewriteRule 集负责重定向,而第二个 RewriteRule 集负责正常的页面处理。
如果没有第一个规则集,所有请求都会在 SSL 虚拟主机下正确加载。
使用第一个规则集,与列出的资源不匹配的重定向工作得很好。例如。请求
https://example.com/about
重定向到
http://example.com/about
但是在请求注册、登录、欢迎和感谢页面时,就会出现问题。这些请求也被重定向到非 ssl 站点,但以损坏的方式。一个请求
https://example.com/signup
重定向到
http://example.com/index.php?q=signup
似乎第一个规则集不匹配(如预期的那样),然后在处理第二个规则集后,再次应用第一个规则集(不是预期的)。
我无法将这种意外行为与任何记录的功能相匹配。
有任何想法吗?
编辑
我在文档中发现了一些模糊的引用,当规则匹配发生在“目录上下文”中时,apache 重新运行规则,但是,引用是关于 .htaccess 的。我的重写发生在我的 <VirtualHost> 标记内的 <Directory> 标记内。我目前正在测试将重写移到 <Directory> 上下文之外——这肯定会改变行为,但我还没有让它按我的需要工作。
编辑2
当规则处理存在于目录上下文中时,该问题肯定是由 apache 重新启动重写处理引起的。我已将规则处理移到 <Directory> 标记之外。但是,现在 RewriteCond 行不起作用......例如。
RewriteCond %{REQUEST_FILENAME} -f
因为 apache 尚未使用 DocumentRoot 将请求的资源解析为文件映射。真是一团糟。
因此,然后我手动将我在 DocumentRoot 中指定的值添加到 RewriteCond。然而,这似乎是一个糟糕的黑客攻击。例如。
RewriteCond /var/www/example.com/public%{REQUEST_FILENAME} -f
所以,现在我正在寻找一种方法来防止 apache 在目录上下文中重新启动重写过程,或者第二好的方法是在 <VirtualHost> 级别指定必要的 RewriteConds 的更好方法。