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

发布于 2024-09-30 06:50:42 字数 612 浏览 1 评论 0原文

我正在使用 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]

任何人都可以建议出了什么问题以及如何修复它吗?

I am using mod_rewrite, to convert subdomains into directory urls. (solution from here). When I explicity write a rule for one subdomain, it works perfectly:

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

However, if I try to match all subdomains, it results in 500 internal error (log says too many redirects). The code is:

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

Can anyone suggest what went wrong and how to fix it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

兰花执着 2024-10-07 06:50:42

你的第二个 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]

Your second RewriteCond will never return false, because you can't use backreferences within your test clauses (they're compiled during parsing, making this impossible since no variable expansion will take place). You're actually testing for paths beginning with the literal text /%1/, which isn't what you wanted. Given that you're operating in a per-directory context, the rule set will end up being applied again, resulting in a transformation like the following:

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

This goes on for about ten iterations before the server gets upset and throws a 500 error. There are a few different ways to fix this, but I'm going to chose one that most closely resembles the approach you were trying to take. I'd also modify that first RewriteCond, since the regular expression is a bit flawed:

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

First, it checks the HTTP_HOST value and captures the subdomain, whatever it might be. Then, assuming you don't want this transformation to take place in the case of www, it makes sure that the capture does not match that. After that, it uses the regular expression's own internal backreferences to see if the REQUEST_URI begins with the subdomain value. If it doesn't, it prepends the subdomain as a directory, like you have now.

The potential problem with this approach is that it won't work correctly if you access a path beginning with the same name as the subdomain the request is sent to, like sub.example.com/sub/. An alternative is to check the REDIRECT_STATUS environment variable to see if an internal redirect has already been performed (that is, this prepending step has already occurred):

RewriteCond %{HTTP_HOST}           ^([^.]+)\.example\.com$ [NC]
RewriteCond %1                     !=www
RewriteCond %{ENV:REDIRECT_STATUS}  =""
RewriteRule .* /%1/$0 [L]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文