代码之家  ›  专栏  ›  技术社区  ›  hourback

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

  •  22
  • hourback  · 技术社区  · 17 年前

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

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

    天哪!

    8 回复  |  直到 17 年前
        1
  •  15
  •   That Brazilian Guy KoalaBear    8 年前

    具体说明 RewriteOptions InheritDown 在父作用域(如httpd.conf)中,无需修改即可在子虚拟主机中应用规则。

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

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

    ( source )

    Apache从2.4.8开始就支持这一点(在原始问题提出时不可用)。

    来自文档 RewriteOptions :

    继承下来

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

    继承之前

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

        2
  •  12
  •   Zava    14 年前

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

    RewriteEngine On
    RewriteOptions Inherit 
    

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

        3
  •  10
  •   Travis Wilson    16 年前

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

    RewriteOptions inherit
    

    每个VirtualHost指令。这至少比摆弄.htaccess文件简单得多。Apache非常清楚这样一个事实

    默认情况下,重写配置为 没有继承。这意味着你 需要重新编写发动机 中每个虚拟主机的指令 您希望使用它。 ( http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html )

    显然,更改默认值的方法是通过子级(vhost或director)中的RewriteOptions,所以你必须这样做 某物 在每个孩子。

        4
  •  5
  •   Jeremy Bourque    17 年前

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

        5
  •  2
  •   Chad A. Davis    15 年前

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

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

    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>
    
        6
  •  1
  •   nyet    8 年前

    您可能希望使用InheritDownBefore,以避免向您的vhost添加更多垃圾。

    全局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>
    

    然后,您可以在每个vhost中执行此操作,而无需其他指令:

    <VirtualHost *:80>
        ....
        <IfModule mod_rewrite.c>
            RewriteEngine On
            RewriteRule ^/.*            /index.php [L,PT]
        </IfModule>
    </VirtualHost>
    
        7
  •  1
  •   Maciek    6 年前

    感谢大家回答以上问题。它帮助我找到了答案。

    问题已经回答了,我只是想添加一个例子,以防你使用谷歌计算引擎。它说它需要 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>
    

    另请注意(用于测试):

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

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

        8
  •  0
  •   Alex Gray    15 年前

    对于我想要的全面指令,我总是使用“包罗万象”的VHost,比如。.....

    Listen 80
    NameVirtualHost *:80
    
    <VirtualHost *:80>
    ErrorLog "/var/log/apache2/error_log"
    </VirtualHost>
    
    <VirtualHost *:80>
    ServerName alloftherestoftheVHosts.com
    DocumentRoot "/ServiceData/.........
    ............ 
    

    它总是 好像 工作……错误日志被正确组合,等等……但这可能是早期/冲突/志同道合的指令的结果。

    个人笔记。。 无论是谁想出了Apache的配置模式和语法,都是一个或一群在洞穴里度过了太多时间的丁巴特。…整个事情应该被清除并XML化,或者别的什么! 尽管两者截然不同。..Hello Kitty的设置过程 Cherokee ..到恶毒的简洁 NGinx 配置。…两者都更符合逻辑。。