gpt4 book ai didi

regex - ^ 字符无法在 htaccess 中进行 mod 重写

转载 作者:行者123 更新时间:2023-12-02 01:33:54 24 4
gpt4 key购买 nike

我在 .htaccess 文件中重写规则时遇到了这个非常烦人的问题。

上下文

所以我想要的是将这两种类型的 URL 重写到不同的目标:

URL 1 -- http://example.com/rem/call/answer/{Hex String}/{Hex String}/
URL 2 -- http://example.com/answer/{Hex String}/{Hex String}/

这是我的 .htaccess 文件的摘录:

RewriteEngine On
RewriteRule rem/call/answer/([a-f0-9]+)/([a-f0-9]+)/?$ /TARGET1
RewriteRule answer/([a-f0-9]+)/([a-f0-9]+)/?$ /TARGET2

问题

现在的问题是 URL 2 重写良好(使用 rule #2)并转到 TARGET 2,但是 URL 1 用两条规则重写,而不仅仅是 rule #1

我尝试了几种解决方案,包括明显使用字符 ^ 来表示 “字符串的开头”。那时,我的重写规则是:

RewriteEngine On
RewriteRule rem/call/answer/([a-f0-9]+)/([a-f0-9]+)/?$ /TARGET1
RewriteRule ^answer/([a-f0-9]+)/([a-f0-9]+)/?$ /TARGET2

然而,另一个问题发生了。这次是 URL 1 重写得很好,只有 rule #1 并转到 TARGET 1。但是现在 URL 2 不再重写了。我猜这是因为第二个重写规则从不匹配任何 url,因此从不应用。

到目前为止,我找到的唯一解决方案是删除 ^ 并在 rule #1 末尾使用 [L] 标志像这样:

RewriteEngine On
RewriteRule rem/call/answer/([a-f0-9]+)/([a-f0-9]+)/?$ /TARGET1 [L]
RewriteRule answer/([a-f0-9]+)/([a-f0-9]+)/?$ /TARGET2

这样,它使用规则 #1,匹配,但永远不会达到规则 #2。两个 url 都使用这些规则正确重写,但这不是一个好的解决方案,因为我可能不想在第一条规则应用后停止重写 URL 1(如果我有第三条规则我会怎样也想申请...)


我的问题

既然我已经陈述了问题,我的问题是:

  1. [L] 标志是唯一的出路吗? (我非常怀疑,当然希望不会)
  2. ^ 会是一个候选解决方案吗? (我也这么认为)
  3. 如果是这样,如何让它发挥作用,为什么在我的情况下它根本不起作用?

我的怀疑

我怀疑这与 URL 实际上是 http://example.com/answer/{Hex String}/{Hex String}/ 而不仅仅是 answer/{Hex String}/{Hex String}/,这意味着 answer/.. 并不是真正在字符串的开头,因此在它前面加上 ^ 不起作用。

但这又让我想到了另一个问题:

如何告诉 apache 去除 scheme+domain 部分的 url(即 http://example.com/)并仅将规则与 url 的其余部分匹配(例如 答案/{十六进制字符串}/{十六进制字符串}/) ?


编辑

我还应该补充一点,我已经尝试过基本的 alice-bob 示例。我的根目录中有一个名为 bob.html 的文件,.htaccess 文件中有以下规则:

RewriteRule alice.html$ /bob.html

这工作得很好,并在查询 alice.html 时显示 bob.html 页面。但是,如果我将规则更改为:

RewriteRule ^alice.html$ /bob.html

然后我在查询 alice.html 页面时收到 404 错误...

至于@anubhava的评论,我完整的.htaccess文件组成如下:

RewriteEngine On

[A bunch of RewriteRule that have nothing to do with the topic at hand
(don't contain any "answer" string in them and all work perfectly)]

RewriteRule rem/call/answer/([a-f0-9]+)/([a-f0-9]+)/?$ /TARGET1 [L]
RewriteRule answer/([a-f0-9]+)/([a-f0-9]+)/?$ /TARGET2

ErrorDocument 404 /404.html
Header set Access-Control-Allow-Origin "*"
SetEnv file_uploads On

最佳答案

好的,感谢@anubhava 的评论,我通过将 .htaccess 文件向下移动一级到 www 目录轻松解决了这个问题。

我仍然很好奇为什么这解决了我的问题,所以我继续研究 apache 的重写是如何工作的。我不确定我是否了解了所有细节,但这是我发现的。

位置位置位置

当然,不用说文件的位置很重要,尤其是像.htaccess 这样的配置文件。但它甚至超越了简单的文件路径,原因如下:

  1. 首先,您需要记住 .htaccess 文件会影响它所在的​​目录及其所有子目录。因此,将全局 .htaccess 文件放在您网站的根目录下似乎合乎逻辑,因为它会影响所有子目录(即整个网站)。

  2. 要记住的第二件事是 public_html 目录(在我的例子中称为 www,只是指向 public_html 的符号链接(symbolic link)) 是您网站内容的根文件夹。您可能有权访问其父目录,但无论您放在 public_html 目录之外的内容本身都不是您网站内容的一部分,您放在那里的任何资源都不会成为您网站层次结构的一部分(即无法通过 http://example.com/path/to/resource) 访问。

  3. 正则表达式选项 ^ 匹配字符串的开头,这里在 URL 重写的上下文中,它是所考虑的 URL 的开头。这还不是全部,Apache 似乎会根据您的 .htaccess 文件的位置来解析匹配。这意味着 ^ 不仅引用了您作为规则的一部分编写的字符串的开头,而且实际上相对于 .htaccess 文件的实际路径引用了它作为该特定 .htaccess 文件中所有重写规则的“本地根目录”。


例子

假设您有一个子目录(例如 http://example.com/sub/directory/)并且其中有两个文件:

http://example.com/sub/directory/.htaccess
http://example.com/sub/directory/bob.html

在此 .htaccess 文件中,您有如下重写规则:

RewriteRule ^tom.html$ /sub/directory/bob.html

此规则不会匹配http://example.com/tom.html,因为您可能期望^ 起作用,而是会匹配http ://example.com/sub/directory/tom.html 因为这是 .htaccess 文件所在的位置。


结论

一般来说,假设您有一个重写规则,例如:

RewriteRule ^PATH$ /TARGET_PATH

这意味着该规则不会将 URL 与 ^PATH$ 匹配,而是实际上将它与 ^[Location of the .htaccess file]/PATH$ 匹配>

换句话说,.htaccess 文件的位置充当其中所有重写规则的一种基本 URL(非常类似于 html 中的基本标记)。

这就是为什么我的 ^ 重写规则不起作用,因为我的 .htaccess 文件位于 public_html 目录之上,并且该父目录充当我的规则的基本 URL。因此,该规则永远不会匹配任何 URL,因为它将它与从未访问过的路径进行比较(因为在网站的内容根目录之上)。

我希望这足够清楚,可以帮助任何可能遇到我遇到的相同问题的人。

干杯

关于regex - ^ 字符无法在 htaccess 中进行 mod 重写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32382651/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com