一般RewriteRule用于URL中的许多未定义参数

时间:2010-04-16 23:25:55

标签: url .htaccess parameters mod-rewrite

我正在尝试编写一条规则,以便可以概括,因为传递值的多个页面是不同的。现在我可以这样做:

RewriteRule ^forum/([^/]{1,255})/([\+]{1})/((([a-z]+)([_]{1})([a-zA-Z0-9]+)([/]?))+)$   forum.php?name=$1&$5=$7 [L]

解决诸如:

Nome+del+Forum/+/page_1/action_do

应该返回:

forum.php?name=Nome+del+Forum&page=1&action=do

相反,只取最后一个参数(在这种情况下 action = do ):

forum.php?name=Nome+del+Forum&action=do

我该如何解决?提前谢谢!

2 个答案:

答案 0 :(得分:0)

最简单的方法是在网站配置中添加RewriteMap prg:foo。请注意,据我所知,您无法在RewriteMap中使用.htaccess

如果您有权访问服务器配置文件,请在全局或<VirtualHost>中添加类似这样的内容:

RewriteMap forum prg:/path/to/forum-rewriter.pl

然后在您选择的.htaccess尝试:

RewriteRule ^forum/.* ${forum:$0} [QSA]

(在您尝试的RewriteRule中,您似乎希望匹配以forum/开头的路径,这就是我在这里所做的。)

接下来,您需要制作forum-rewriter.pl

#!/usr/bin/perl

use strict;
use warnings;


$| = 1;
while ($_ = <STDIN>) {
    chomp($_);
    if (s,^forum/([^/]+)(/\+)?(/.*)?,forum.php?name=$1, && $3) {
        my $query_string = $3;
        $query_string =~ s,/([^/_]+)_([^/_]+),&$1=$2,g;
        $_ .= $query_string;
    }
    print "$_\n";
}

确保chmod 755 /path/to/forum-rewriter.pl

RewriteMap将使Apache在启动时为每个httpd进程启动forum-rewriter.pl一次。每次RewriteRule的模式匹配时,它都会写入forum-rewriter.pl的标准输入的路径。 forum-rewriter.pl将在URL上完成其工作(如果有的话)并将结果打印回Apache。

仅供参考,我很容易测试forum-rewriter.pl。只需运行它并开始发送路径:

$ /tmp/forum-rewriter.pl
forum/Nome+del+Forum/+/page_1/action_do
forum.php?name=Nome+del+Forum&page=1&action=do
forum/Nome+del+Forum/page_1/action_do
forum.php?name=Nome+del+Forum&page=1&action=do
forum/Nome+del+Forum
forum.php?name=Nome+del+Forum
foo
foo

如果您无法使用RewriteMap,我认为可以使用mod_rewrite ,但我认为这很危险

RewriteCond %{ENV:SetForumName} =""
RewriteRule ^forum/([^/]+)(/\+)?(/.*)? /forum.php$3?name=$1 [QSA,E=SetForumName:1]
RewriteCond %{ENV:SetForumName} !=""
RewriteRule ^forum.php/([^/_]+)_([^/_]+)(/.*)? /forum.php$3?$1=$2 [N,QSA]

这很危险,因为[N]导致Apache在第二个RewriteRule匹配时重新开始处理所有重写规则。如果你不小心,你将创建一个无限循环,Apache将要求500或呱呱叫。还要注意它设置SetForumName环境变量的副作用。但是,这是我能够找到告诉mod_rewrite在查询字符串中使用foo_bar的路径中替换所有 foo=bar的唯一方法。“

答案 1 :(得分:0)

类似于this

另请参阅this了解更多信息。

基本信息是这些规则

RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*/)([^/]+)/([^/]+) $1?$2=$3&%1 [L]
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^([^/]+)/ $1?%1 [L]

将重写以下内容

/mypage/param1/val1/param2/val2/param3/val3/...     --->
/mypage?param1=val1&param2=val2&param3=val3&...

它接受第一个参数并调用该页面。其余参数将转换为查询字符串。

编辑更多有关代码如何工作的内容。

第一行(和第三行)仅捕获“?”之后的所有内容。这样它就可以添加回重写URL的末尾。同一件事情 可以使用[QSA]标志完成,但我更喜欢这样做 明确地说它是可见的。

该字符串保存在%1变量中。

第二行使用正则表达式将URL拆分为三个部分。

$ 2和$ 3是路径的最后两部分。 1美元就是之前的一切。

所以这个:

/mypage/param1/val1/param2/val2/param3/val3/param4/val4/param5/val5/

成为这个:

$1                                                        $2      $3
/mypage/param1/val1/param2/val2/param3/val3/param4/val4/  param5  val5

并重写为此(为了便于阅读而添加了空格):

/mypage/param1/val1/param2/val2/param3/val3/param4/val4/ ? param5 = val5

如果您的URL使用除斜杠之外的分隔符,则可以修改常规 相应的表达。

[L](“last”)标志阻止其余规则运行。 但是 - 这是关键 - mod_rewrite使用new调用webserver URL和新URL再次通过mod_rewrite发送!这有时被称为mod_rewrite递归,正是你想要的工作。

下一次,接下来的两个部分被剥离并添加 到查询字符串。

此:

$1                                           $2      $3     %1
/mypage/param1/val1/param2/val2/param3/val3  param4  val4 ? param5=val5

成为这个:

/mypage/param1/val1/param2/val2/param3/val3 ? param4 = val4 & param5=val5

这会一直发生,直到URL的所有部分都转换为 查询字符串的一部分。当发生这种情况时,第二行不匹配 但第四行呢。这就是为您提供调用的最终URL的原因 你想要的节目。上面的链接显示了略有不同的变化的答案 允许不同的规则。

另请注意,mod_rewrite的次数有限制 可以递归。请参阅设置 {。1}} .htaccess和 MaxRedirects 在你的apache conf文件中。