.htaccess中单个RewriteCond的多个RewriteRules

时间:2011-08-28 00:00:46

标签: apache .htaccess mod-rewrite

我的.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用于多个规则行。

5 个答案:

答案 0 :(得分:57)

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

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

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

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

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

答案 1 :(得分:31)

变量必须保存为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]

答案 2 :(得分:7)

显然,这并不是很有趣,特别是当事情发展变得更加复杂时。但是,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/

我认为这很有帮助

答案 3 :(得分:4)

通常,您不能在单个RewriteCond之后使用多个RewriteRule语句。但如果你愿意,你可以根据自己的条件做一个小技巧,如下所示:

https://serverfault.com/questions/162586/one-rewritecond-for-multiple-rewriterules

http://www.sant-media.co.uk/2010/03/applying-rewritecond-to-multiple-rewriterule-in-htaccess/

答案 4 :(得分:3)

从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