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

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

我的虚拟主机中有以下用于 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>

我的目的是将任何不匹配(注册|登录|欢迎|谢谢)的页面请求重定向到非 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。

答案1

我建议将以下内容添加到您的配置中,这将为您提供有关 mod_rewrite 正在做什么以及为什么这样做的详细日志。这可能有助于澄清您为什么会有这样的行为:

RewriteLog /tmp/rewrite.log
RewriteLogLevel 9

一旦完成了分析,请务必删除这些行,因为它们会影响性能。

答案2

我决定采用以下解决方案,将重写放在任何 <Directory ...> 部分之外。这样我就可以将任何不应使用 SSL 的请求重定向到非 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>

相关内容