有条件地包含Apache配置

时间:2019-02-20 13:08:26

标签: apache .htaccess

在多域设置中,我使用具有以下条件的巨大的.htaccess文件,以根据请求的URL的HTTP_HOST跳过很多重写规则。

RewriteCond %{HTTP_HOST} !^www\.example\.com$
## skip next 1000 rules, if we`re not on the .com domain.
RewriteRule .? - [S=1000]
RewriteRule ^foo https://www.example.com/bar [R=301,L]
...
RewriteCond %{HTTP_HOST} !^www\.example\.co\.uk$
## skip next 500 rules, if we`re not on the .co.uk domain. 
RewriteRule .? - [S=500]
RewriteRule ^foo https://www.example.co.uk/bar [R=301,L]
...

由于我有多个域,总共有大约4000条重写规则,所以我宁愿将配置拆分为几个文件并根据当前的HTTP_HOST加载这些文件。

是否可以在表达式中使用include指令代替

"RewriteRule .? - [S=500]"

类似这样的东西:

<If "%{HTTP_HOST} =~ ^www\.example\.com$">
    Include conf/com.rewriterules.conf
</If>

还是有更好的方法来解决这个问题?

1 个答案:

答案 0 :(得分:1)

  

我们无法更改服务器设置,因此维护重写规则的唯一方法是htaccess。

您无法在.htaccess中执行此操作,因为您无法在Include文件中使用.htaccess指令。没有其他方法可以包含配置文件。而且,有条件地包括此条件的唯一方法是使用<If>块。

您可能会将所有指令都放在<If>块中,而不是使用[S=1000]标志。但是,这并非没有严重的警告。在<If>表达式被尽早处理的同时,<If>块的内容在请求中被 late (“ last”)合并。实际上,在请求已映射到文件系统之后,它似乎合并得很晚。这意味着RewriteRule伪指令与解析的文件系统路径而不是请求的URL路径匹配!因此,这需要在任何RewriteRule指令中加以考虑-或更改为使用mod_alias RedirectRedirectMatch进行外部重定向,该重定向始终作用于请求的URL。

您可以潜在地在服务器配置中执行此操作(使用Include块内的<If>指令)。但是,上述警告同样适用-<If>块被合并为很晚

但是,请注意,您的语法不太正确。如果您希望匹配一个正则表达式,那么您会在正则表达式周围缺少斜杠分隔符。它应显示为:

<If "%{HTTP_HOST} =~ /^www\.example\.com$/">
    Include conf/com.rewriterules.conf
</If>

或者使用更简单的字符串/相等比较:

<If "%{HTTP_HOST} == 'www.example.com'">
:

但是,最好不要在每个域中使用单独的<If>,而在每个vHost中只需使用<VirtualHost>必要的文件,而不是使用Include块。没有警告。


撇开一点,但是...如果您的所有“重写规则”都是外部重定向(如您的示例),否则将导致404(即它们不存在)的请求,那么您不应该不能以Apache配置(.htaccess或服务器配置)开始所有这些重定向。

它们应该在您的应用程序逻辑中,并且仅在您的应用程序确定其将导致404时“延迟”处理。这将优先考虑正常的网站流量,而不是对重定向进行优先级排序。通过Apache配置中的重定向,可以在每个单个请求上对它们进行处理-这通常是不必要的。


RewriteRule ^foo https://www.example.com/bar [R=301,L]
:
RewriteRule ^foo https://www.example.co.uk/bar [R=301,L]

也许只是您的示例代码,但您无需在RewriteRule 替代中为外部重定向指定绝对URL。它可能是相对于根的:/bar