RewriteBase如何在.htaccess中工作

mtb9vblg  于 2022-12-13  发布在  其他
关注(0)|答案(9)|浏览(155)

我在一些.htaccess示例中看到过这种情况

RewriteBase /

它在功能上似乎有点类似于HTML的<base href="">
我相信它可能会自动将它的值前置到RewriteRule语句的开头(可能是没有前导斜杠的语句)?
我不能让它正常工作。我认为它的使用可以为站点的可移植性带来很大的方便,因为我经常有一个与生产服务器不同的开发服务器。我目前的方法让我删除了我的RewriteRule语句的一部分。
有没有人能简单地向我解释一下如何实施它?
谢谢

hl0ma9xz

hl0ma9xz1#

RewriteBase仅适用于***相对***重写规则的*目标

  • 像这样使用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重写规则对 * 相对URL * 执行 *HTTP重定向 *(而不仅仅是静默重写)

在这些情况下,您可能会发现需要指定RewriteBase。
然而,由于这是一个令人困惑的指令,通常最好在重写目标中简单地指定绝对(也称为“根相对”)URI。阅读您的规则的其他开发人员将更容易理解这些规则。

在htaccess文件中,mod_rewrite的工作方式类似于<Directory><Location>容器,并且RewriteBase用于提供相对路径基。
例如,假设您有以下文件夹结构:

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

因此,您可以访问:

  • http://example.com/(根目录)
  • http://example.com/subdir1(子目录1)
  • http://example.com/subdir2(子目录2)
  • 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中剥离该部分。重写基础对此没有影响,这只是每个目录的工作方式。

rewrite base * 所做的 * 是为规则的target中的任何相对路径**提供一个URL路径基(* 不是 * 文件路径基)。

RewriteRule ^foo$ bar.php [L]

bar.php是相对路径,与以下路径相对:

RewriteRule ^foo$ /bar.php [L]

其中/bar.php是绝对路径。绝对路径 * 总是 * 是“root”(在上面的目录结构中)。这意味着不管规则是在“root”、“subdir1”、“subsubdir”等等中,/bar.php路径总是Map到http://example.com/bar.php
但另一个规则(使用相对路径)基于该规则所在的目录。

RewriteRule ^foo$ bar.php [L]

在“root”目录中,如果您转到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”被添加到base的末尾。实际上,这个例子通常不是你想要的,因为你不能在同一个目录容器或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”目录。

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

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

RewriteBase /subdir2/subsubdir/

就是这样。

0yycz8jy

0yycz8jy2#

用我自己的话来说,在阅读了这些文档并进行了实验之后:
可以使用RewriteBase为重写提供一个 base

# 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参数。

twh00eeo

twh00eeo3#

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

RewriteBase myfolder

如果mod_rewrite无法正常工作。
试图用它来实现一些不寻常的事情,而不是解决这个问题听起来像是一个食谱变得非常困惑。

6xfqseft

6xfqseft4#

RewriteBase仅在只能将.htaccess放在站点根目录的情况下有用。否则,最好将不同的.htaccess文件放在站点的不同目录中,并完全省略RewriteBase指令。
最近,对于复杂的站点,我已经把它们去掉了,因为这使得从测试到上线部署文件只需要多一个步骤就可以了。

41ik7eoe

41ik7eoe5#

当我开发时,它在一个文件夹中的不同域上。当我启动一个站点时,那个文件夹不再存在。使用RewriteBase允许我在两个环境中使用相同的.htaccess文件。
实时:

RewriteBase /
# RewriteBase /dev_folder/

开发时:

# RewriteBase /
RewriteBase /dev_folder/
piok6c0g

piok6c0g6#

我找到的最清楚的解释不是在当前的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文档继续给予“关于内部处理步骤的详细信息”。
经验教训:虽然我们需要熟悉“当前”,但宝石可以在编年史中找到。

5tmbdcev

5tmbdcev7#

此命令可以显式设置重写的基URL。如果希望从域的根目录开始,则应在RewriteRule之前包含以下行:

RewriteBase /
iugsix8n

iugsix8n8#

我相信这段来自Apache文档的摘录很好地补充了前面的答案:
当您在每个目录(htaccess)上下文中的替换中使用相对路径时,需要此指令,除非满足以下任一条件:

  • 原始请求和替换位于DocumentRoot之下(与通过其他方式(如Alias)访问相对)。
  • 指向包含RewriteRule的目录的文件系统路径(后缀为相对替换)作为服务器上的URL路径也是有效的(这种情况很少见)。

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

axr492tv

axr492tv9#

我只是删除了.htaccess文件,它就可以完美运行了

相关问题