【问题标题】:^ character not working on mod rewrite in htaccess^ 字符不适用于 htaccess 中的 mod 重写
【发布时间】:2015-11-29 16:52:08
【问题描述】:

.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 去除方案+域部分的 url(即http://example.com/)并仅将规则与 url 的其余部分匹配(例如answer/{Hex String}/{Hex String}/)?


编辑

我还应该补充一点,我已经尝试了基本的 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

【问题讨论】:

  • 出于好奇,TARGET 中是否有“答案”?
  • 嗯……“回答”是什么意思?
  • 里面是否有字符串answer。例如:RewriteRule ^answer/(.*)$ /some/path/answer/foo.php?字符串“answer”是否出现在规则的目标中?
  • 是的,它会重定向到“answer.php”页面,其中包含查询字符串中捕获的两个十六进制代码。顺便说一句,我编辑了我的问题以添加一个细节,这让我相信这不是问题(或只是其中一个问题)。
  • 是的 RewriteRule ^alice.html$ /bob.html 应该可以工作。不应该在www目录吗?

标签: regex apache .htaccess mod-rewrite url-rewriting


【解决方案1】:

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

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

位置位置位置

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

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

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

  3. 正则表达式选项 ^ 匹配字符串的开头,在 URL 重写的上下文中,它是所考虑的 URL 的开头。这还不是全部,似乎 Apaches 会相对于您的 .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,因为它会将其与从未访问过的路径进行比较(因为在网站的内容根目录之上)。

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

干杯

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多