【问题标题】:How does RewriteBase work in .htaccessRewriteBase 如何在 .htaccess 中工作
【发布时间】:2010-10-16 18:55:28
【问题描述】:

我在几个.htaccess 示例中看到了这一点

RewriteBase /

它在功能上似乎与 HTML 的 <base href=""> 有点相似。

我相信它可能会自动将其值添加到 RewriteRule 语句的开头(可能没有前导斜杠)?

我无法让它正常工作。我认为它的使用对于站点可移植性非常方便,因为我经常有一个与生产服务器不同的开发服务器。我目前的方法让我从RewriteRule 语句中删除部分内容。

谁能简单解释一下如何实现它?

谢谢

【问题讨论】:

标签: .htaccess mod-rewrite


【解决方案1】:

用我自己的话来说,在阅读了文档并进行了实验之后:

您可以使用RewriteBase 为您的重写提供一个基础。考虑一下这个

# invoke rewrite engine
    RewriteEngine On
    RewriteBase /~new/

# add trailing slash if missing
    rewriteRule ^(([a-z0-9\-]+/)*[a-z0-9\-]+)$ $1/ [NC,R=301,L]

这是我用来确保 URL 尾部有斜杠的真实规则。这将转换

http://www.example.com/~new/page

http://www.example.com/~new/page/

通过在其中添加RewriteBase,您可以使相对路径脱离RewriteBase 参数。

【讨论】:

  • “去掉 RewriteBase 参数” - 你的意思是 rewriteRule 参数吗? :)
  • 我想澄清一些关于 htaccess 的细节。ReWriteBase 是否为 htaccess 中的所有规则设置了它以下它的声明是什么?有没有办法取消设置,可以重置吗?
  • @Kissaki:不,$1 匹配带括号的 RewriteRule 模式,但替换的相对路径来自 RewriteBase 参数。因此,结果替换为/~new/$1/
  • @Damon:请参阅 this question 了解多个 RewriteBase 指令。简而言之,您不能拥有多个 - 我认为 last RewriteBase 指令获胜,并影响整个 .htaccess 文件。
  • -1;这个答案似乎对其他人有所帮助,但对我来说完全不透明。我可以猜到 “您可以使用 RewriteBase 为您的重写提供基础” - 这几乎只是单词的重新排列 - 但我不知道什么是“基础” is 在这种情况下,如果删除 RewriteBase 行,您给出的示例的含义也会有所不同。关闭手册我去......
【解决方案2】:

RewriteBase 仅在您只能将 .htaccess 放在站点根目录的情况下才有用。否则,您最好将不同的 .htaccess 文件放在站点的不同目录中并完全省略 RewriteBase 指令。

最近,对于复杂的网站,我一直在将其删除,因为它使从测试到实际部署文件的过程更加复杂。

【讨论】:

  • 虽然这可能是个好建议,但这根本不是问题的答案。因此,它应该是对该问题的评论,没有收到(尽可能多的)赞成票,并且绝对不被接受为“答案”。
  • “最好将不同的 .htaccess 文件放在不同的目录中” - 我不确定这是个好建议吗?将 .htaccess 文件散布在您的网站上会使调试/维护成为一场噩梦。我会说最好在您网站的根目录中有一个 .htaccess 文件。
  • @w3d 还有一个时间问题:每次访问子目录时,都会解析多个 .htaccess 文件(从根目录到当前子目录)。与根目录中的单个文件相比,拥有大量文件可能会降低对请求的整体响应速度,即使它包含很多规则。..
【解决方案3】:

此命令可以为您的重写显式设置基本 URL。如果您希望从域的根目录开始,您可以在 RewriteRule 之前添加以下行:

RewriteBase /

【讨论】:

    【解决方案4】:

    AFAIK,RewriteBase 仅用于修复 mod_rewrite 在.htaccess 文件中而不是在站点根目录中运行的情况,并且它猜测它正在运行的文件夹的错误 Web 路径(而不是文件系统路径) . 因此,如果您在映射到http://example.com/myfolder 的文件夹中的 .htaccess 中有 RewriteRule,您可以使用:

    RewriteBase myfolder
    

    如果 mod_rewrite 无法正常工作。

    试图用它来实现一些不寻常的事情,而不是解决这个问题,这听起来像是一个让你非常困惑的秘诀。

    【讨论】:

    【解决方案5】:

    当我开发时,它位于文件夹内的不同域中。当我上线一个网站时,该文件夹不再存在。使用 RewriteBase 允许我在两种环境中使用相同的 .htaccess 文件。

    直播时:

    RewriteBase /
    # RewriteBase /dev_folder/
    

    开发时:

    # RewriteBase /
    RewriteBase /dev_folder/
    

    【讨论】:

    • 我确信这不会总是有效。例如,如果您在 RewriteCond 指令中使用 %{REQUEST_URI} 会怎样?
    • @user1669830,如果您只有一个重写器,您可以将基础添加到重写器stackoverflow.com/a/46541685/632951
    【解决方案6】:

    我相信 Apache 文档的这段摘录很好地补充了之前的答案:

    当您使用相对路径时,需要此指令 在每个目录(htaccess)上下文中替换,除非其中任何一个 以下条件为真:

    • 原始请求和替换位于 DocumentRoot 下(与通过其他方式(例如别名)可访问相反)。

    • 包含 RewriteRule 的目录的文件系统路径(以相对替换为后缀)作为 URL 路径也有效 服务器(这种情况很少见)。

    如前所述,在其他情况下,只有使 你的规则更短。此外,同样如前所述,您可以 通过将 htaccess 文件放在 子目录。

    【讨论】:

      【解决方案7】:

      我找到的最清楚的解释不是在当前的 2.4 apache 文档中,而是在 version 2.0

      #  /abc/def/.htaccess -- per-dir config file for directory /abc/def
      #  Remember: /abc/def is the physical path of /xyz, i.e., the server
      #            has a 'Alias /xyz /abc/def' directive e.g.
      
      RewriteEngine On
      
      #  let the server know that we were reached via /xyz and not
      #  via the physical path prefix /abc/def
      RewriteBase   /xyz
      

      它是如何工作的?对于 apache 黑客,这个 2.0 文档继续提供“有关内部处理步骤的详细信息。”

      经验教训:虽然我们需要熟悉“当前”,但可以在编年史中找到宝石。

      【讨论】:

        【解决方案8】:

        RewriteBase 仅适用于 relative 重写规则的目标

        • 像这样使用 RewriteBase...

          RewriteBase /folder/
          RewriteRule a\.html b.html
          
        • 本质上与...相同

          RewriteRule a\.html /folder/b.html
          
        • 但是当 .htaccess 文件在 /folder/ 中时,这也指向同一个目标:

          RewriteRule a\.html b.html
          

        虽然文档暗示始终使用 RewriteBase,但 Apache 通常会正确检测到 DocumentRoot 下的路径,除非:

        • 您正在使用Alias 指令

        • 您正在使用 .htaccess 重写规则执行 HTTP 重定向(而不仅仅是静默重写)到 相对 URL

        在这些情况下,您可能会发现需要指定 RewriteBase。

        但是,由于它是一个令人困惑的指令,通常最好在重写目标中简单地指定绝对(也称为“根相对”)URI。阅读您的规则的其他开发人员会更容易掌握这些规则。



        引用Jon Lin's excellent in-depth answer here:

        在 htaccess 文件中,mod_rewrite 的工作方式类似于 <Directory><Location> 容器。 RewriteBase 用于提供相对路径基础。

        例如,假设您有这样的文件夹结构:

        DocumentRoot
        |-- subdir1
        `-- subdir2
            `-- subsubdir
        

        所以你可以访问:

        • http://example.com/(根)
        • http://example.com/subdir1 (subdir1)
        • http://example.com/subdir2 (subdir2)
        • http://example.com/subdir2/subsubdir(子目录)

        通过RewriteRule 发送的 URI 与包含 htaccess 文件的目录相关。所以如果你有:

        RewriteRule ^(.*)$ - 
        
        • 在根htaccess中,请求为/a/b/c/d,则捕获的URI($1)为a/b/c/d
        • 如果规则在subdir2 中并且请求是/subdir2/e/f/g,那么捕获的URI 是e/f/g
        • 如果规则在subsubdir中,请求是/subdir2/subsubdir/x/y/z,那么捕获的URI是x/y/z

        规则所在的目录已从 URI 中剥离了该部分。重写基础对此没有影响,这只是每个目录的工作方式。

        重写基础所做 的作用是为 规则的目标中的任何相对路径提供 URL 路径基础(不是 文件路径基础) 。所以说你有这个规则:

        RewriteRule ^foo$ bar.php [L]
        

        bar.php 是相对路径,而不是:

        RewriteRule ^foo$ /bar.php [L]
        

        /bar.php 是绝对路径。绝对路径将始终为“根”(在上面的目录结构中)。这意味着无论规则是否在“root”、“subdir1”、“subsubdir”等中,/bar.php 路径始终映射到http://example.com/bar.php

        但是另一个规则,相对路径,它基于规则所在的目录。所以如果

        RewriteRule ^foo$ bar.php [L]
        

        在“根”中,您转到http://example.com/foo,您将获得http://example.com/bar.php 的服务。但是,如果该规则位于“subdir1”目录中,并且您转到http://example.com/subdir1/foo,您将获得http://example.com/subdir1/bar.php。等等。这有时有效,有时无效,正如文档所说,它应该是相对路径的必需,但大多数时候它似乎有效。除非您正在重定向(使用R 标志,或者因为您的规则目标中有http://host 而隐含)。这意味着这条规则:

        RewriteRule ^foo$ bar.php [L,R]
        

        如果它在“subdir2”目录中,并且您转到 http://example.com/subdir2/foo,mod_rewrite 会将相对路径误认为是文件路径而不是 URL 路径,并且由于 R 标志,您将结束被重定向到类似的东西:http://example.com/var/www/localhost/htdocs/subdir1。这显然不是你想要的。

        这就是 RewriteBase 的用武之地。该指令告诉 mod_rewrite 将什么附加到每个相对路径的开头。所以如果我有:

        RewriteBase /blah/
        RewriteRule ^foo$ bar.php [L]
        

        在“subsubdir”中,转到http://example.com/subdir2/subsubdir/foo 实际上会为我服务http://example.com/blah/bar.php。 “bar.php”被添加到基数的末尾。在实践中,这个例子通常不是你想要的,因为你不能在同一个目录容器或 htaccess 文件中有多个碱基。

        在大多数情况下,它是这样使用的:

        RewriteBase /subdir1/
        RewriteRule ^foo$ bar.php [L]
        

        这些规则在“subdir1”目录中的位置,并且

        RewriteBase /subdir2/subsubdir/
        RewriteRule ^foo$ bar.php [L]
        

        将在“subsubdir”目录中。

        这部分允许您使您的规则可移植,因此您可以将它们放在任何目录中,并且只需要更改基础而不是一堆规则。例如,如果您有:

        RewriteEngine On
        RewriteRule ^foo$ /subdir1/bar.php [L]
        RewriteRule ^blah1$ /subdir1/blah.php?id=1 [L]
        RewriteRule ^blah2$ /subdir1/blah2.php [L]
        ...
        

        这样转到http://example.com/subdir1/foo 将服务http://example.com/subdir1/bar.php 等。假设您决定将所有这些文件和规则移动到“subsubdir”目录。与其将/subdir1/ 的每个实例都更改为/subdir2/subsubdir/,不如只使用一个基础:

        RewriteEngine On
        RewriteBase /subdir1/
        RewriteRule ^foo$ bar.php [L]
        RewriteRule ^blah1$ blah.php?id=1 [L]
        RewriteRule ^blah2$ blah2.php [L]
        ...
        

        然后当您需要将这些文件和规则移动到另一个目录时,只需更改基础:

        RewriteBase /subdir2/subsubdir/
        

        就是这样。

        【讨论】:

        • 对我来说,我错过了RewriteEngine On。例如,在 1and1 上不需要,但在我的专用服务器上需要它。
        • 详细的简短回答:RewriteBase 指令的工作原理amitoverflow.com/2020/12/06/…
        猜你喜欢
        • 2015-11-16
        • 1970-01-01
        • 2023-03-16
        • 2013-05-17
        • 2013-08-27
        • 2020-06-21
        • 1970-01-01
        • 2017-08-22
        • 1970-01-01
        相关资源
        最近更新 更多