【问题标题】:Multiple RewriteRules for single RewriteCond in .htaccess.htaccess 中单个 RewriteCond 的多个 RewriteRules
【发布时间】:2011-11-05 07:10:44
【问题描述】:

我的 .htaccess 中有以下命令

    RewriteCond %{HTTP_HOST} ^(www\.)?([a-z0-9-]+)\.example\.com [NC]
    RewriteRule ^(.*?)-([a-z]+) %2/$1.$2 [L]
    RewriteRule ^(.*?)-([0-9]+)([a-z]) %2/$1$3.$2 [L]

%2 在第二行和以后的行中不起作用。 我可以为 %2 定义任何变量并在所有 RewriteRule 命令中使用它吗? 以下命令有效

     RewriteCond %{HTTP_HOST} ^(www\.)?([a-z0-9-]+)\.example\.com [NC]
     RewriteRule ^(.*?)-([a-z]+) %2/$1.$2 [L]
     RewriteCond %{HTTP_HOST} ^(www\.)?([a-z0-9-]+)\.example\.com [NC]
     RewriteRule ^(.*?)-([0-9]+)([a-z]) %2/$1$3.$2 [L]

但我想在不重复条件的情况下将 %2 用于多个规则行。

【问题讨论】:

标签: apache .htaccess mod-rewrite


【解决方案1】:

您可以使用 RewriteRule 标志 S|skip 将多个 RewriteRules 绑定到单个 RewriteCond(或一组 RewriteConds)。这是一个将一个条件应用于三个规则的示例:

RewriteCond  %{HTTP_HOST}  !^www.mydomain.com$
# skip rules if NOT within domain - only way to tie multiple rules to one cond
RewriteRule  .?  -  [S=3]
RewriteRule  ^path1(/.*)$  /otherpath1$1
RewriteRule  ^path2(/.*)$  /otherpath2$1
RewriteRule  ^path3(/.*)$  /otherpath3$1

要将现有条件更改为适用于多个规则,您必须:

  • 否定条件(以 ! 开头)
  • 如果您有多个 RewriteCond:
    将 Cond 中的逻辑 AND 更改为 OR,反之亦然。
  • 在要与条件相关联的所有规则前面添加跳过重写规则。将 S 参数设置为要跳过的规则行数。

请注意,不能在跳过的规则中使用任何指向 RewriteCond(如 %1)的反向引用。这些只能在跳过的 RewriteRule 中访问。

【讨论】:

  • 这仅解决了逻辑部分,而不是反向引用部分,因为RewriteCond 在技术上仍然只适用于第一个RewriteRule。原始问题确实需要反向引用。
  • 我在我的回答者@rustyx 的最后一句中提到了这一点。我仍然认为许多不需要反向引用的用户会阅读这篇文章并享受基于跳过的解决方案。
  • @Jpsy 任何可能跳过的规则都可以有自己的条件吗?如果是这样,这会影响在S 参数中设置的内容吗?
  • @JAAulde 我猜不是。我从未尝试过,但文档只谈论跳过 RewriteRules,而不是 Conds。但是你应该看看新的指令 。它们从 Apache 2.4 开始可用,可能会解决您的问题。见httpd.apache.org/docs/2.4/expr.html#examples
  • @Jpsy,谢谢!是的,我想使用<If>,但目前使用的是 Apache 2.2。
【解决方案2】:

该变量必须保存为 Apache var,然后才能在没有重复条件的情况下使用。

保存在 Apache 变量中显示在第二行。第 3 行和第 4 行保存的变量的用法。

RewriteCond %{HTTP_HOST} ^(www\.)?([a-z0-9-]+)\.example\.com [NC]
RewriteRule .? - [E=Wa:%1,E=Wb:%2]
RewriteRule ^(.*?)-([a-z]+) %{ENV:Wb}/$1.%{ENV:Wb} [L]
RewriteRule ^(.*?)-([0-9]+)([a-z]) %{ENV:Wb}/$1$3.$2 [L]

【讨论】:

  • 正是我需要的侯赛因!
  • 您可以在想要虚拟子域的地方使用 Wb 变量。
【解决方案3】:

显然,这并不好玩,尤其是随着事情的发展和变得越来越复杂。但是,RewriteRule 语句有一个鲜为人知的选项,它告诉 apache 跳过下一个 N 个 RewriteRule 语句。 [S=N]。因此,不是每次都检查请求是否不是文件并且不是目录,我们可以这样做: 代码块

#
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [S=3]
RewriteRule ^([^./]+)/$ http://www.santweb.co.uk/$1 [L]
RewriteRule ^([^./]+)/([^./]+)/$ http://www.santweb.co.uk/$1/$2 [L]
RewriteRule ^([^./]+)/([^./]+)/([^./]+)/$ http://www.santweb.co.uk/$1/$2/$3 [L]

#

我发现了这个,来自:http://www.sant-media.co.uk/2010/03/applying-rewritecond-to-multiple-rewriterule-in-htaccess/

我觉得有帮助

【讨论】:

  • 是的,不好玩。应该有人告诉 Apache 的人有关 if/else 块的信息。谢谢。
【解决方案4】:

从 Apache 2.4 开始,您可以使用 <If> 指令:

RewriteEngine On
<If "%{HTTP:Upgrade} == 'websocket'">
    RewriteRule /nidoran/(.*)           ws://localhost:8080/nidoran/$1 [P,L]
    RewriteRule /kakuna/(.*)           ws://localhost:8081/kakuna/$1 [P,L]
    RewriteRule /porygon/(.*)           ws://localhost:8082/porygon/$1 [P,L]
</If>

http://httpd.apache.org/docs/2.4/expr.html#examples

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    • 2020-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多