在RewriteRule中引用多个RewriteCond的捕获组

时间:2013-07-22 10:13:40

标签: .htaccess mod-rewrite

当我将多个RewriteCond链接在一起时,只能使用%0 - %9引用最后一个RewriteCond的捕获组。

在以下问题中,url的查询字符串中的参数可以是任何顺序。要将它们解析为一个奇特的URL,我需要单独匹配查询字符串中的每个参数:

RewriteCond %{QUERY_STRING} param1=([^&]+)
RewriteCond %{QUERY_STRING} param2=([^&]+)
RewriteCond %{QUERY_STRING} param3=([^&]+)
RewriteRule ^foo$ bar/%1/%2/%3/ [R]

就像我指出的......这不起作用。为了解决这个问题,我可以在下一个RewriteCond中引用前一个RewriteCond的捕获组,并将每个参数“传播”到实际的RewriteRule:

RewriteCond %{QUERY_STRING} param1=([^&]+)
RewriteCond %1&%{QUERY_STRING} ^([^&]*)&.*param2=([^&]+)
RewriteCond %1&%2&%{QUERY_STRING} ^([^&]*)&([^&]*)&.*param3=([^&]+)
RewriteRule ^foo$ bar/%1/%2/%3/ [R]

这应该可行,但是对于每个额外的参数,它会变得更加混乱。另一个解决方案可能是解析一个参数并在每个参数之后重定向客户端(导致冗长的重定向链,我想避免)。

是否有更简洁的方法来访问RewriteRule中所有RewriteCond的捕获组(例如,是否可以命名它们或将它们分配给变量,以便我可以在其他地方引用它们?)

2 个答案:

答案 0 :(得分:10)

您可以尝试在重写条件中构建目标URL:

RewriteCond ##%{QUERY_STRING}      (.*)##(|.*&)param1=([^&]+)
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param2=([^&]+)
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param3=([^&]+)
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param4=([^&]+)
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param5=([^&]+)
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param6=([^&]+)

RewriteRule ^foo$ /bar%1/%3? [L,R]

当我尝试请求时:

/foo?param1=a&param2=b&param6=3&param3=4&param5=5&param4=6

我被重定向到:

/bar/a/b/4/6/5/3

添加任何其他必需的查询字符串参数不会使它看起来比现在更麻烦。

答案 1 :(得分:1)

在进行了一些实验之后,可以将所有参数解析为环境变量并像这样使用它们。我怀疑它是非常有效的,我认为任何需要这种结构的用例都会更好地使用php页面路由器。对于花哨的网址,Jon Lin的解决方案可能会更好。然而它确实模仿了我的想法。

但是,我会把代码放在这里进行演示:

#Parse all query key-value pairs to an environment variable with the q- prefix
RewriteCond %{QUERY_STRING} ^([^=]*)=([^&]*)(&(.*)|$)$
RewriteRule ^(.*)$ $1?%4 [E=q-%1:%2,N]

#If 'param1' existed in the query string...
RewriteCond %{ENV:q-param1} !^$
RewriteRule ^foo$ bar/%{ENV:q-param1} [END]

甚至......

#Keep the original query string
RewriteCond %{ENV:qstring} ^$
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule .* - [E=qstring:#%1]

#parse the query parameters to environment variables
RewriteCond %{ENV:qstring} ^#([^=]*)=([^&]*)(&(.*)|$)$
RewriteRule ^(.*)$ - [E=q-%1:%2,E=qstring:#%4,N]

#See that the original query string is still intact
RewriteCond %{ENV:q-param1} !^$
RewriteRule ^foo$ bar/%{ENV:q-param1} [QSA]