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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/344588/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 17:00:40  来源:igfitidea点击:

How can I implement a global RewriteCond / RewriteRule in Apache that applies to all virtual hosts?

apachemod-rewritevirtualhost

提问by hourback

The title pretty much says it all. :-) I have lots of virtual hosts and I want to put a single rewriting block at the top of the httpd.conf file that rewrites URLs no matter which virtual host the request might be directed to. How the heck do I do this?

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

I found thisbut my question is the same: how can I do this without resorting to .htaccess files and performing some other action for each virtual host?

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

OMGTIA!

奥姆蒂亚!

采纳答案by Matej Snoha

Specify RewriteOptions InheritDownin the parent scope (such as httpd.conf) to get your rules applied in child Virtual Hosts without modifing them.

指定RewriteOptions InheritDown父范围(如httpd.conf)中获得儿童虚拟主机应用的规则,而不对矫正他们。

This will only work on Virtual Hosts where the RewriteEnginedirective is set to on:

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

Note that rewrite configurations are not inherited by virtual hosts. This means that you need to have a RewriteEngine on directive for each virtual host in which you wish to use rewrite rules.

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

(source)

来源

Apache supports this since 2.4.8 (not available at the time of the original question).

Apache 从 2.4.8 开始支持这个(在原始问题时不可用)。

From documentation for RewriteOptions:

从文档中RewriteOptions

InheritDown

If this option is enabled, all child configurations will inherit the configuration of the current configuration. It is equivalent to specifying RewriteOptions Inherit in all child configurations. See the Inherit option for more details on how the parent-child relationships are handled. Available in Apache HTTP Server 2.4.8 and later.

InheritDownBefore

Like InheritDown above, but the rules from the current scope are applied before rules specified in any child's scope. Available in Apache HTTP Server 2.4.8 and later.

IgnoreInherit

This option forces the current and child configurations to ignore all rules that would be inherited from a parent specifying InheritDown or InheritDownBefore. Available in Apache HTTP Server 2.4.8 and later.

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

向下继承

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

继承DownBefore

与上面的 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

回答by Zava

By default, mod_rewrite configuration settings from the main server context are not inherited by virtual hosts. To make the main server settings apply to virtual hosts, you must place the following directives in each <VirtualHost>section:

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

RewriteEngine On
RewriteOptions Inherit 

click http://httpd.apache.org/docs/2.2/mod/mod_rewrite.htmlto find more information

单击http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html以查找更多信息

回答by Travis Wilson

Looks like the simplest possible solution is to add

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

RewriteOptions inherit

to each VirtualHost directive. This is at least a lot simpler than messing with .htaccess files. Apache is pretty clear on the fact that

到每个 VirtualHost 指令。这至少比弄乱 .htaccess 文件要简单得多。Apache 非常清楚的事实是

by default, rewrite configurations are not inherited. This means that you need to have a RewriteEngine on directive for each virtual host in which you wish to use it. (http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html)

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

and apparently the way to change the default is via RewriteOptions in the child (vhost or director), so you have to do somethingin each child.

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

回答by Jeremy Bourque

I've never tested it, so it might not work, but I would try adding an includedirective in all of the virtual host blocks to a single file. You would have to change each virtual host configuration block once, but after that, you should have a central place from which to make changes. YMMV.

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

回答by Chad A. Davis

If you're only trying to rewrite something in the domain part of the name, e.g. to fix a common misspelling, you don't even need the 'inherit' option. I setup a no-name virtual host to catch all invalid host names and respell them correctly before redirecting them.

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

Since this uses redirects, the appropriate virtual host will be found after the rewrites have been applied.

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

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 [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} [C]
RewriteRule ^([^.]+\.)?domain.com(.*) http://domain.com [L,R=301]

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

回答by Alex Gray

I've always used a "catch-all" VHost for directives I wanted across the board, like......

对于我想要的指令,我一直使用“包罗万象”的 VHost,例如......

Listen 80
NameVirtualHost *:80

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

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

And it's always seemedto work... error logs were getting combined properly, etc...... but it IS possible that this was the result of an earlier / conflicting / like-minded directive.

而且它似乎总是 有效......错误日志被正确组合,等等......但这可能是早期/冲突/志同道合的指令的结果。

Personal note.. Whoever dreamed up the Apache configuration schema and syntax was a dingbat, or a group of dingbats, who spent too much time in their cave.... The whole thing should be exorcised and XMLized, or something!Although they are both wildly different... the Hello-Kitty setup process of Cherokee.. to the viciously succinct NGinxconfig.... are both so much more logical..

个人笔记.. 想出 Apache 配置模式和语法的人是一个 dingbat 或一群 dingbats,他们在他们的洞穴中度过了太多时间......整个事情应该被驱除和 XML 化,或者其他什么!尽管它们都大不相同...... Cherokee的 Hello-Kitty 设置过程......到极其简洁的NGinx配置......都更加合乎逻辑......

回答by nyet

You may want to use InheritDownBefore to avoid having to add more junk to your vhosts.

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

An example of a global letsencrypt alias:

全局 letencrypt 别名的示例:

# 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>

Then you can do this in each of your vhosts, with no other directives:

然后你可以在你的每个虚拟主机中做到这一点,没有其他指令:

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

回答by Jeffrey the Giraffe

Thanks to everyone to answered above. It helped me find my answer.

谢谢楼上的大家解答。它帮助我找到了答案。

Question has been answered already, I just wanted to add an example in case you are using Google Compute Engine. It says it requires Apache HTTP Server 2.4.8BUT it works with Apache/2.4.25 (Debian). Even when I try to upgrade, I cannot go past Apache/2.4.25. It says this version is the latest version.

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

Here's an example of how to implement.

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

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>

ALSO OF NOTE (For Testing):

另请注意(用于测试):

When you are testing your rewrite engine. It is really easy to get confused about if it is working or not because of cache and cookies. If you got it to work once on a browser, it will continue to work even if you delete the rewrite code. Testing rewrite is really annoying sometimes. You might think it works but then it stops or starts.

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

Best way to test rewrite code is to open an incognito tab in your browser, clear or cookies and cache. Open developer mode just in case. DO NOT JUST REFRESH. You need to click into the URL and refresh. Or open new tab. Or copy/paste URL into new window. If you use same window with refresh, it might be just redoing results from the past instead of renewing the new code.

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