如何在 Apache 中实现适用于所有虚拟主机的全局 RewriteCond / RewriteRule?

Posted

技术标签:

【中文标题】如何在 Apache 中实现适用于所有虚拟主机的全局 RewriteCond / RewriteRule?【英文标题】:How can I implement a global RewriteCond / RewriteRule in Apache that applies to all virtual hosts? 【发布时间】:2010-09-25 13:36:47 【问题描述】:

标题几乎说明了一切。 :-) 我有很多虚拟主机,我想在 httpd.conf 文件的顶部放置一个重写块,无论请求可能被定向到哪个虚拟主机,它都会重写 URL。我该怎么做?

我找到了this,但我的问题是一样的:如何在不借助 .htaccess 文件并对每个虚拟主机执行其他操作的情况下做到这一点?

OMGTIA!

【问题讨论】:

天哪。我难倒了所有人。 【参考方案1】:

感谢大家在上面回答。它帮助我找到了答案。

问题已经得到解答,我只是想添加一个示例,以防您使用 Google Compute Engine。它说它需要Apache HTTP Server 2.4.8 但它适用于Apache/2.4.25 (Debian)。即使我尝试升级,我也无法通过Apache/2.4.25。它说这个版本是最新版本。

这是一个如何实现的示例。

RewriteOptions InheritDown
RewriteCond %HTTP_HOST ^www\. [NC,OR]
RewriteCond %HTTP_HOST !\.co$ [NC]
RewriteCond %HTTP_HOST ^(?:www\.)?(.+)\.[^.]+$ [NC]
RewriteRule ^ https://%1.co%REQUEST_URI [L,NE,R=301]
<VirtualHost *:80>
 RewriteEngine On
 ServerAlias *.*
</VirtualHost>

另请注意(用于测试):

当您测试您的重写引擎时。由于缓存和cookies,很容易混淆它是否工作。如果你让它在浏览器上工作一次,即使你删除了重写代码,它也会继续工作。测试重写有时真的很烦人。您可能认为它有效,但随后它停止或启动。

测试重写代码的最佳方法是在浏览器中打开一个隐身标签,清除或清除 cookie 和缓存。打开开发者模式以防万一。不要只是刷新。您需要单击 URL 并刷新。或打开新标签。或将 URL 复制/粘贴到新窗口中。如果您使用相同的窗口进行刷新,它可能只是重做过去的结果,而不是更新新代码。

【讨论】:

【参考方案2】:

您可能希望使用 InheritDownBefore 以避免向您的虚拟主机添加更多垃圾。

全局letsencrypt别名示例:

# letsencrypt
<IfModule alias_module>
    Alias /.well-known/ /var/www/html/.well-known/
</IfModule>
<IfModule mod_rewrite.c>
    # prevent vhost rewrites from killing the alias
    RewriteEngine On
    RewriteOptions InheritDownBefore
    RewriteCond %REQUEST_URI ^/\.well\-known
    RewriteRule . - [L,PT]
</IfModule>

然后您可以在每个虚拟主机中执行此操作,无需其他指令:

<VirtualHost *:80>
    ....
    <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteRule ^/.*            /index.php [L,PT]
    </IfModule>
</VirtualHost>

【讨论】:

【参考方案3】:

在父作用域(例如 httpd.conf)中指定 RewriteOptions InheritDown 以在不修改子虚拟主机的情况下应用您的规则。

这仅适用于 RewriteEngine 指令设置为 on 的虚拟主机:

请注意,虚拟主机不会继承重写配置。这意味着您需要为每个希望使用重写规则的虚拟主机设置一个 RewriteEngine on 指令。

(source)

Apache 从 2.4.8 开始支持此功能(在原始问题出现时不可用)。

来自RewriteOptions 的文档:

InheritDown

如果启用此选项,所有子配置将继承当前配置的配置。相当于在所有子配置中指定 RewriteOptions Inherit。有关如何处理父子关系的更多详细信息,请参阅继承选项。 在 Apache HTTP Server 2.4.8 及更高版本中可用。

InheritDownBefore

与上面的 InheritDown 类似,但当前作用域中的规则在任何子作用域中指定的规则之前应用。 在 Apache HTTP Server 2.4.8 及更高版本中可用。

忽略继承

此选项强制当前和子配置忽略将从指定 InheritDown 或 InheritDownBefore 的父级继承的所有规则。 在 Apache HTTP Server 2.4.8 及更高版本中可用。

(http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriteoptions)

【讨论】:

请注意,这仍然需要在虚拟主机部分中设置RewriteEngine On "请注意,虚拟主机不会继承重写配置。这意味着您需要为每个希望使用重写规则的虚拟主机设置一个 RewriteEngine on 指令。" httpd.apache.org/docs/2.4/mod/mod_rewrite.html 另外请注意,我使用的是 Apache/2.4.25 (Debian) 并且 InheritDown 仍然有效。但是每个虚拟主机中都需要RewriteEngine On。不知道为什么它说 2.4.8。我正在将 GCE 与 Apache (2.4.25) Debian Stretch 一起使用。当我尝试更新时,它还说这是最新版本。【参考方案4】:

默认情况下,来自主服务器上下文的 mod_rewrite 配置设置不会被虚拟主机继承。要将主服务器设置应用于虚拟主机,您必须在每个 &lt;VirtualHost&gt; 部分中放置以下指令:

RewriteEngine On
RewriteOptions Inherit 

点击http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html了解更多信息

【讨论】:

【参考方案5】:

我一直使用“包罗万象”的 VHost 来处理我想要的指令,比如......

Listen 80
NameVirtualHost *:80

<VirtualHost *:80>
ErrorLog "/var/log/apache2/error_log"
</VirtualHost>

<VirtualHost *:80>
ServerName alloftherestoftheVHosts.com
DocumentRoot "/ServiceData/.........
............ 

而且它总是似乎工作......错误日志正在正确组合,等等......但这可能是早期/冲突/喜欢的结果 -有意识的指令。

个人笔记.. 想出 Apache 配置架构和语法的人是一个 dingbat,或者是一群 dingbat,他们在洞穴中花费了太多时间......整个事情应该被驱除和 XML 化,什么的!虽然它们都截然不同......从Cherokee..的Hello-Kitty设置过程到简洁的nginx配置......都更加合乎逻辑...... p>

【讨论】:

“包罗万象”的虚拟主机仅在没有其他虚拟主机适用时才适用。 (?)【参考方案6】:

如果您只是想重写名称的域部分中的某些内容,例如要修复常见的拼写错误,您甚至不需要“继承”选项。我设置了一个无名虚拟主机来捕获所有无效的主机名并在重定向它们之前正确地重新拼写它们。

由于这使用重定向,因此在应用重写后会找到适当的虚拟主机。

Options +Indexes +FollowSymLinks
RewriteEngine on
# If it begins with only domain.com, prepend www and send to www.domain.com
RewriteCond %HTTP_HOST ^domain [NC]
RewriteRule ^(.*) http://www.domain.com$1 [L,R=301]

# Correct misspelling in the domain name, applies to any VirtualHost in the domain
# Requires a subdomain, i.e. (serviceXXX.)domain.com, or the prepended www. from above
RewriteCond %HTTP_HOST ^([^.]+\.)dommmmmain\.com\.?(:[0-9]*)?$ [NC]
RewriteRule ^(.*) %HTTP_HOST$1 [C]
RewriteRule ^([^.]+\.)?domain.com(.*) http://$1domain.com$2 [L,R=301]

# No-name virtual host to catch all invalid hostnames and mod_rewrite and redirect them
<VirtualHost *>
    RewriteEngine on
    RewriteOptions inherit
</VirtualHost>

【讨论】:

我以为您说您甚至不需要“继承”选项,但您将其包含在 规则中 我们使用它来修正我们域名的拼写。在这种情况下,仅对通配符 VirtualHost 使用“继承”就足够了。如果您有更复杂的重写选项,那么您可能需要在每个 VirtualHost 中包含“继承”。 啊,所以你的意思是你不需要每个虚拟主机中的“继承”选项。明白了。 "请注意,虚拟主机不会继承重写配置。这意味着您需要为每个希望使用重写规则的虚拟主机设置一个 RewriteEngine on 指令。" httpd.apache.org/docs/2.4/mod/mod_rewrite.html【参考方案7】:

看起来最简单的解决方案是添加

RewriteOptions inherit

到每个 VirtualHost 指令。这至少比处理 .htaccess 文件要简单得多。 Apache 非常清楚

默认情况下,重写配置是 不继承。这意味着你 需要开启 RewriteEngine 每个虚拟主机的指令 您希望使用它。 (http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html)

显然更改默认值的方法是通过子项(虚拟主机或导演)中的 RewriteOptions,因此您必须在每个子项中执行 一些操作

【讨论】:

从 Apache 2.4.8 开始可以使用 httpd.conf(或其他)和RewriteOptions InheritDown,相当于在所有 vhosts 中指定RewriteOptions Inherit @MatejSnoha ,您想提交您的评论作为问题的解决方案吗?对于寻求解决此问题的其他人来说,它可能会变得更加明显。我自己无法对此进行测试,但我很想知道它是否对其他人有帮助。【参考方案8】:

我从未测试过它,所以它可能不起作用,但我会尝试在所有虚拟主机块中添加一个include 指令到一个文件中。您必须更改每个虚拟主机配置块一次,但在那之后,您应该有一个可以进行更改的中心位置。 YMMV。

【讨论】:

对我来说最好的答案 :) 因为它不限于 mod_rewrite,而是适用于任何 Apache 功能/指令。

以上是关于如何在 Apache 中实现适用于所有虚拟主机的全局 RewriteCond / RewriteRule?的主要内容,如果未能解决你的问题,请参考以下文章

需要在 iOS 应用程序(适用于奥地利地区)中实现虚拟钱包,用户可以在其中通过积分向卖家付款,我可以实时获得收益 [关闭]

如何在python中实现适用于N维特征向量的GMM聚类EM算法(期望最大化算法)

RecyclerView onClickListener 适用于所有片段

地理位置仅适用于本地主机

你如何在 C++ 中实现阶乘函数? [复制]

如何在 QuickSelect 中实现重复