【问题标题】:Back-reference only works in first RewriteRule after RewriteCond反向引用仅适用于 RewriteCond 之后的第一个 RewriteRule
【发布时间】:2014-06-22 05:09:40
【问题描述】:

背景:

我们开发了一个粗略的内容管理系统,以便我们可以构建新闻部分、产品评论部分等,与我们的网站集成。这些“官方”CMS 站点应该可以在例如http://www.oursite.com/news 获得。我们也希望为我们的社区成员提供“非官方”网站;这些将在例如http://membername.oursite.com 上提供。我们将确保官方和非官方名称之间没有冲突。

问题:

这是 .htaccess 的摘录:

###################################################
# Redirect localhost.dev to www.localhost.dev #
###################################################
RewriteCond %{HTTP_HOST} ^localhost.dev$ [NC]
RewriteRule ^(.*)$ http://www.localhost.dev/$1 [R=301,L]

##################################################################
# UNOFFICIAL HOSTED sites - redirect mysite.localhost.dev URLs #
##################################################################
RewriteCond %{HTTP_HOST} !^www. [NC]
RewriteCond %{HTTP_HOST} ^([a-z0-9_-]+)\.localhost\.dev$ [NC]
RewriteRule ^/?$ hosted/index.php?site=%1 [NC,QSA,L]
RewriteRule ^post/?$ hosted/posting.php?site=%1 [NC,QSA,L]

##########################################################################
# OFFICIAL HOSTED sites - redirect www.localhost.dev/officialblog URLs   #
# Rationale: If /directory_name doesn't exist, maybe it's a hosted site. #
#            Pass it to hosted site handler, which will 404 if not       #
##########################################################################
RewriteCond %{HTTP_HOST} ^www.localhost.dev$ [NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-z0-9_-]+)/?$ hosted/index.php?site=$1 [NC,QSA,L]
RewriteRule ^([a-zA-z0-9_-]+)/post/?$ hosted/posting.php?site=$1 [NC,QSA,L]

第一部分和最后一部分给出了预期的行为。造成麻烦的是“非官方托管网站”部分。

http://unofficialblog.localhost.dev/ 有效 - 在 hosts/index.php 中,$_GET['site'] 是“非官方博客”。 http://unofficialblog.localhost.dev/post 不起作用 - 在 hosts/posting.php 中,$_GET['site'] 是 ""。

我的尝试

交换这两个 RewriteRules 的顺序,反之亦然。所以看来 %1 只在第一个有效,在第二个无效。

如果我这样做:

##################################################################
# UNOFFICIAL HOSTED sites - redirect mysite.localhost.dev URLs #
##################################################################
RewriteCond %{HTTP_HOST} !^www. [NC]
RewriteCond %{HTTP_HOST} ^([a-z0-9_-]+)\.localhost\.dev$ [NC]
RewriteRule ^/?$ hosted/index.php?site=%1 [NC,QSA,L]
RewriteCond %{HTTP_HOST} !^www. [NC]
RewriteCond %{HTTP_HOST} ^([a-z0-9_-]+)\.localhost\.dev$ [NC]
RewriteRule ^post/?$ hosted/posting.php?site=%1 [NC,QSA,L]

那么 $_GET['site'] 在这两种情况下都是“非官方博客”。

但这太难看了,我有大约十个这样的 RewriteRules。是否有一种更简洁的方法可以在所有这些 RewriteRules 中保持对子域的反向引用?

编辑:看起来像 Multiple RewriteRules for single RewriteCond in .htaccess 的重复,我昨天搜索时没有找到。

【问题讨论】:

标签: .htaccess mod-rewrite


【解决方案1】:

只有在一组重写条件之后的第一个重写规则才是与一组条件“相关”的规则。以下是条件工作原理的元分解:

  RewriteCond a1 (can evaluate  references from rule a)
  RewriteCond a2 (can evaluate  references from rule a)
  RewriteRule a <--the conditions a1, a2 apply only to things matching this rule
  RewriteRule b <--the conditions a1, a2 are not applicable to this rule

要使它们同时适用于这两个规则,您需要这样做:

  RewriteCond a1 (can evaluate  references from rule a)
  RewriteCond a2 (can evaluate  references from rule a)
  RewriteRule a

  RewriteCond copy of a1 (can evaluate  references from rule b)
  RewriteCond copy of a2 (can evaluate  references from rule b)
  RewriteRule b

【讨论】:

  • 所以我在“官方”部分得到正确的结果纯粹是盲目的运气......现在我再测试一些,我发现确实如此。不过,没有比这更清洁的方法了吗?
  • @EdDaniel 是的,我想看看为什么(最后提到的)非官方版本没有传递参数进行替换。
  • @EdDaniel 哦,您可以尝试将新的完整网址放在最前面,而不是相对网址。
  • @EdDaniel Doh... 在最后一个示例中,第二条规则的条件失败。您是匹配正则表达式的第二个条件字符串不应以 .dev$ 结尾,而应以 .dev/post$ 结尾
  • @EdDaniel 查看我对答案的更新,明确显示不匹配条件和规则
猜你喜欢
  • 2023-03-15
  • 1970-01-01
  • 2013-04-04
  • 2014-10-20
  • 1970-01-01
  • 2013-07-21
  • 2010-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多