RewriteBase 如何在 .htaccess 中工作

我已经在一些.htaccess的例子中看到了这一点

RewriteBase /

它在功能上似乎有点类似于HTML的

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

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

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

谢谢

483819 次浏览

用我自己的话说,在阅读了文档和实验之后:

你可以使用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只在你只能把.htaccess放在你站点根目录的情况下有用。否则,你最好将不同的.htaccess文件放在站点的不同目录下,完全忽略RewriteBase指令。

最近,对于复杂的站点,我已经把它们去掉了,因为这使得从测试到实时的文件部署再复杂一步。

这个命令可以显式地为重写设置基本URL。如果你想从你的域的根开始,你可以在你的RewriteRule之前包括以下一行:

RewriteBase /

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

RewriteBase myfolder

如果mod_rewrite不能正常工作。

试图用它来实现一些不寻常的东西,而不是解决这个问题,听起来像是一个非常混乱的配方。

当我开发时,它在一个文件夹中的另一个域中。当我启动一个网站时,这个文件夹就不存在了。使用RewriteBase可以让我在两个环境中使用相同的.htaccess文件。

当生活:

RewriteBase /
# RewriteBase /dev_folder/

当开发:

# RewriteBase /
RewriteBase /dev_folder/

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

类中使用相对路径时,此指令是必需的 在每个目录(htaccess)上下文中的替换,除非 以下条件为真:

  • 原始请求和替换都在DocumentRoot的下面(与其他方法(如别名)不同)。

  • 包含RewriteRule的目录的文件系统路径,以相对替换作为后缀,也可以作为上的URL路径有效 服务器(这是罕见的)。

如前所述,在其他上下文中,它只对make有用 你的规则变短了。此外,正如前面提到的,您可以 中的htaccess文件可以达到同样的效果 子目录。< / p >

我发现最清楚的解释不在当前的2.4 apache文档中,而是在版本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文档继续提供了“关于内部处理步骤的详细信息”。

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

RewriteBase只应用于< em > < / em >相对重写规则的< em > < / em >目标

  • 像这样使用RewriteBase…

    RewriteBase /folder/
    RewriteRule a\.html b.html
    
  • is essentially the same as...

    RewriteRule a\.html /folder/b.html
    
  • But when the .htaccess file is inside /folder/ then this also points to the same target:

    RewriteRule a\.html b.html
    

Although the docs imply always using a RewriteBase, Apache usually detects it correctly for paths under the DocumentRoot unless:

  • You are using Alias directives

  • You are using .htaccess rewrite rules to perform HTTP redirects (rather than just silent rewriting) to relative URLs

In these cases, you may find that you need to specify the RewriteBase.

However, since it's a confusing directive, it's generally better to simply specify absolute (aka 'root relative') URIs in your rewrite targets. Other developers reading your rules will grasp these more easily.



Quoting from Jon Lin's excellent in-depth answer here:

In an htaccess file, mod_rewrite works similar to a <Directory> or <Location> container. and the RewriteBase is used to provide a relative path base.

For example, say you have this folder structure:

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

所以你可以访问:

  • http://example.com/(根)
  • http://example.com/subdir1 (subdir1)
  • http://example.com/subdir2 (subdir2)
  • http://example.com/subdir2/subsubdir (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是绝对路径。绝对路径将总是作为“根”(在上面的目录结构中)。这意味着无论规则是否在“根”、“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 /blah/
RewriteRule ^foo$ bar.php [L]

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

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

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/

就是这样。

我简单地删除。htaccess文件,它运行完美