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

我正在使用mod_rewrite将子域转换为目录URL. (解决方案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]

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

最佳答案
您的第二个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]

转载注明原文:.htaccess-mod_rewrite正则表达式(重定向太多) - 代码日志