mod_rewrite正则表达式(重定向太多)

时间:2010-11-01 14:44:42

标签: .htaccess mod-rewrite subdomain wildcard-subdomain

我正在使用mod_rewrite将子域名转换为目录网址。 (解决方案from here)。当我明确地为一个子域编写规则时,它完美地运行:

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]

任何人都可以建议出现问题以及如何解决问题吗?

1 个答案:

答案 0 :(得分:3)

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

path -> sub/path
sub/path -> sub/sub/path
sub/sub/path -> sub/sub/sub/path
...

这会在服务器被扰乱之前持续大约十次迭代并抛出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]