%N回溯在RewriteCond中的使用

18

我正在开发一种虚拟域名系统。我已经设置了一个通配符DNS作为*.loc,并且我正在尝试修改我的.htaccess文件。以下代码可行:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www.)?example\.loc$ [NC]
RewriteCond %{REQUEST_URI} !^/example/
RewriteRule (.*) /example/$1 [L,QSA]

但是,我希望这个功能适用于我输入的任何内容。然而,我需要将%{REQUEST_URI}与作为域名找到的文本进行检查。我尝试使用以下代码:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www.)?([a-zA-Z0-9-]*.)?([a-zA-Z0-9-]+)\.loc$ [NC]
RewriteCond %{REQUEST_URI} !^/%3/
RewriteRule (.*) /%3/$1 [L,QSA]

但是这行代码 RewriteCond %{REQUEST_URI} !^/%3/ 会导致我的代码抛出内部服务器错误。我理解这是因为我的代码中的 %N,但有没有一种方法可以处理它?我需要这行代码,否则,我的代码会因为内部重定向而失败。
希望有人能理解我的意思。我只需要能够在后续的 RewriteCond 中回溯引用一个 RewriteCond。
1个回答

49

这里有两个你做错了的事情。

首先,你%{HTTP_HOST}的正则表达式不好。你需要转义.,否则它们将被视为“除换行符以外的任何字符”。这实际上使得%3反向引用TLD前主机名的最后一个字符(例如http://blah.bar.loc%3 = r)。

其次,你不能在RewriteCond的正则表达式中使用反向引用,只能在左侧字符串中使用,这是一种奇怪的限制。但是,你可以在正则表达式中使用\1引用,以便构建一个聪明的左侧字符串来匹配。例如%3::%{REQUEST_URI},然后你可以像这样匹配:!^(.*?)::/\1/?。这个正则表达式本质上是说:“匹配并捕获::之前的文本块,然后确保::之后的文本块以/(第一个文本块)开头。”

所以你的规则应该像这样:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?([a-zA-Z0-9-]*\.)?([a-zA-Z0-9-]+)\.loc$ [NC]
RewriteCond %3::%{REQUEST_URI} !^(.*?)::/\1/?
RewriteRule (.*) /%3/$1 [L,QSA]

1
谢谢!我真的不知道那行代码到底是干什么的,但它能用。目前来说,我对此感到满意。非常感谢你的帮助 :) - Connor Deckers
3
这个地方在哪里有记录?这个回答应该得到更多的赞。我投票支持我们取消接受答案,发放悬赏并重新接受答案。 - Jim Rubenstein
1
有没有任何文档链接?双冒号(::)是用来做什么的? - Edik Mkoyan
1
@EdikMkoyan "::" 只是一种匹配 "%3::%{REQUEST_URI}" 的方式。你可以使用任何你想要的,但它只需要不太可能出现在 URI 的一部分即可。 - Jon Lin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接