如何防止apache在“目录上下文”中重新启动重写处理

我有我的虚拟主机SSL连接(我非SSL SSL虚拟主机看起来相同,但没有第一个规则设置redirect)以下内容。

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> 

我的意图是将任何不匹配的页面请求(注册|login|欢迎|谢谢)redirect到非SSL虚拟主机而不作进一步处理,否则不要redirect,而是在SSL虚拟主机内处理请求。

第一个RewriteRule集合照顾redirect,而第二个RewriteRule集合照顾正常的页面处理。

如果没有第一个规则集,所有请求都将在SSL虚拟主机下正确加载。

使用第一个规则集,redirect工作得很好,与列出的资源不匹配。 例如。 请求

 https://example.com/about 

redirect到

 http://example.com/about 

但是在请求注册,login,欢迎和谢谢页面时,会出现问题。 这些请求也被redirect到非SSL网站,但以破碎的方式。 请求

 https://example.com/signup 

redirect到

 http://example.com/index.php?q=signup 

看起来第一个规则集是不匹配的(如预期的那样),那么在第二个规则集被处理之后,第一个规则集被再次应用(不是预期的)。

我无法将这种意外的行为与任何logging的function相匹配。

有任何想法吗?

编辑

我在文档中发现了一些模糊的引用,当apache在“目录上下文”中发生规则匹配时重新运行规则,但引用是关于.htaccess的。 我的重写发生在我的<VirtualHost>标签内的<Directory>标签内。 我目前正在testing在<Directory>上下文之外移动重写 – 这当然似乎改变了行为,但是我还没有按照我的需要进行工作。

EDIT2

当规则处理存在于目录上下文中时,这个问题肯定是由apache重启重写处理引起的。 我移动了<Directory>标签之外的规则处理。 但是,现在RewriteCond行不起作用…例如。

 RewriteCond %{REQUEST_FILENAME} -f 

因为apache尚未使用DocumentRoot将请求的资源parsing为文件映射。 真是一团糟。

所以,我手动将我在DocumentRoot中指定的值预先添加到RewriteCond中。 但是,这似乎是一个可怜的黑客。 例如。

 RewriteCond /var/www/example.com/public%{REQUEST_FILENAME} -f 

所以,现在我正在寻找一种方法来防止apache在目录上下文中重新启动重写过程,或者第二个更好的方法是在<VirtualHost>级别指定必要的RewriteConds。

我build议将下面的内容添加到你的configuration中,这会给你一个mod_rewrite正在做什么的详细日志,以及为什么。 这可能有助于澄清你为什么有这样的行为:

 RewriteLog /tmp/rewrite.log RewriteLogLevel 9 

完成分析之后,请确保删除这些行,因为它们会影响性能。

我已经解决了以下解决scheme,将重写放在任何<目录…>部分之外。 这允许我将任何不应该SSL的请求redirect到非SSL站点,同时允许通过SSL(图像,CSS,js等)提供任何静态内容。

 <VirtualHost ...> ... RewriteEngine on RewriteCond $1 !=signup RewriteCond $1 !=login RewriteCond $1 !=welcome RewriteCond $1 !=thankyou RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d RewriteRule ^/(.*)$ http://example.com/$1 [R=303,QSA,L] RewriteCond %{REQUEST_URI} !=/favicon.ico RewriteCond %{REQUEST_URI} !=/robots.txt RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d RewriteRule ^/(.+)$ /index.php?q=$1 [QSA,L] ... </VirtualHost>