1

我正在使用mod_rewrite, 将子域转换为目录 url。(来自这里的解决方案)。当我明确地为一个子域编写规则时,它可以完美运行:

RewriteCond %{HTTP_HOST}   ^[www\.]*sub-domain-name.domain-name.com [NC]
RewriteCond %{REQUEST_URI} !^/sub-domain-directory/.*
RewriteRule   ^(.*)  /sub-domain-directory/$1  [L]

但是,如果我尝试匹配所有子域,则会导致 500 内部错误(日志显示重定向过多)。代码是:

RewriteCond %{HTTP_HOST}   ^[www\.]*([a-z0-9-]+).domain-name.com [NC]
RewriteCond %{REQUEST_URI} !^/%1/.*
RewriteRule   ^(.*)  /%1/$1  [L]

谁能建议出了什么问题以及如何解决?

4

1 回答 1

3

您的第二个 RewriteCond 永远不会返回 false,因为您不能在测试子句中使用反向引用(它们是在解析过程中编译的,因此这不可能,因为不会发生变量扩展)。您实际上是在测试以文字 text 开头的路径/%1/,这不是您想要的。鉴于您在每个目录的上下文中操作,规则集最终将再次应用,从而导致如下所示的转换:

路径 -> 子/路径
子/路径 -> 子/子/路径
子/子/路径 -> 子/子/子/路径
...

在服务器不正常并引发 500 错误之前,这会持续大约十次迭代。有几种不同的方法可以解决此问题,但我将选择一种与您尝试采用的方法最相似的方法。我还要修改第一个 RewriteCond,因为正则表达式有点缺陷:

RewriteCond %{HTTP_HOST}       ^([^.]+)\.example\.com$ [NC]
RewriteCond %1                !=www
RewriteCond %1#%{REQUEST_URI} !^([^#]+)#/\1/
RewriteRule .* /%1/$0 [L]

首先,它检查 HTTP_HOST 值并捕获子域,无论它可能是什么。然后,假设您不希望这种转换发生在 www 的情况下,它会确保捕获不匹配。之后,它使用正则表达式自己的内部反向引用来查看 REQUEST_URI 是否以子域值开头。如果没有,它会将子域作为目录添加到前面,就像现在一样。

这种方法的潜在问题是,如果您访问以与请求发送到的子域同名的路径开头的路径,例如sub.example.com/sub/ ,它将无法正常工作。另一种方法是检查 REDIRECT_STATUS 环境变量以查看是否已经执行了内部重定向(即,这个前置步骤已经发生):

RewriteCond %{HTTP_HOST}           ^([^.]+)\.example\.com$ [NC]
RewriteCond %1                     !=www
RewriteCond %{ENV:REDIRECT_STATUS}  =""
RewriteRule .* /%1/$0 [L]
于 2010-11-02T06:20:38.140 回答