RewriteCond以任何顺序匹配查询字符串参数

时间:2013-01-13 19:35:50

标签: apache .htaccess mod-rewrite redirect url-rewriting

我有一个可能包含三个参数的网址:

  1. ?类别=计算机
  2. &安培;子类别=笔记本
  3. &安培;产物=戴尔灵-15
  4. 我需要301将此网址重定向到其友好版本:

    http://store.example.com/computers/laptops/dell-inspiron-15/
    

    我有这个,但是如果查询字符串参数是以任何其他顺序,则无法使其工作:

    RewriteCond %{QUERY_STRING} ^category=(\w+)&subcategory=(\w+)&product=(\w+) [NC]
    RewriteRule ^index\.php$ http://store.example.com/%1/%2/%3/? [R,L]
    

3 个答案:

答案 0 :(得分:16)

您可以通过多个步骤实现此目的,方法是检测一个参数,然后转发到下一步,然后重定向到最终目的地

RewriteEngine On

RewriteCond %{QUERY_STRING} ^category=([^&]+) [NC,OR]
RewriteCond %{QUERY_STRING} &category=([^&]+) [NC]
RewriteRule ^index\.php$ $0/%1

RewriteCond %{QUERY_STRING} ^subcategory=([^&]+) [NC,OR]
RewriteCond %{QUERY_STRING} &subcategory=([^&]+) [NC]
RewriteRule ^index\.php/[^/]+$ $0/%1

RewriteCond %{QUERY_STRING} ^product=([^&]+) [NC,OR]
RewriteCond %{QUERY_STRING} &product=([^&]+) [NC]
RewriteRule ^index\.php/([^/]+/[^/]+)$ http://store.example.com/$1/%1/? [R,L]

要避免OR和双重条件,您可以使用

RewriteCond %{QUERY_STRING} (?:^|&)category=([^&]+) [NC]

正如@TrueBlue建议的那样。

另一种方法是在 TestString QUERY_STRING前面添加&符号&,并始终检查

RewriteCond &%{QUERY_STRING} &category=([^&]+) [NC]

此技术(前缀 TestString )也可用于将已找到的参数传送到下一个RewriteCond。这使我们可以将三个规则简化为一个

RewriteCond &%{QUERY_STRING} &category=([^&]+) [NC]
RewriteCond %1!&%{QUERY_STRING} (.+)!.*&subcategory=([^&]+) [NC]
RewriteCond %1/%2!&%{QUERY_STRING} (.+)!.*&product=([^&]+) [NC]
RewriteRule ^index\.php$ http://store.example.com/%1/%2/? [R,L]

!仅用于将已找到和已重新排序的参数与QUERY_STRING分开。

答案 1 :(得分:3)

我对这种事情略有不同,利用ENV VAR设置并通过mod_rewrite 读取。我发现通过这样的名称引用反向引用更具可读性/可维护性,这些ENV VAR也可以在以后的请求处理中重用。总的来说,我认为它比这里接受的答案更强大,更灵活。无论如何,它对我来说效果很好。我完整地复制了我的要点:

来自https://gist.github.com/cweekly/5ee064ddd551e1997d4c

# Mod_rewrite is great at manipulating HTTP requests.
# Using it to set and read temp env vars is a helpful technique.
#
# This example walks through fixing a query string:
# Extract good query params, discard unwanted ones, reorder good ones, append one new one.
#
# Before: /before?badparam=here&baz=w00t&foo=1&bar=good&mood=bad
# After: /after?foo=1&bar=good&baz=w00t&mood=happy
#
# Storing parts of the request (or anything you want to insert into it) in ENV VARs is convenient.
# Note the special RewriteRule target of "-" which means "no redirect; simply apply side effects"
# This lets you manipulate the request at will over multiple steps.
#
# In a RewriteRule, set custom temp ENV VARs via [E=NAME:value]
# Note it's also possible to set multiple env vars
# like [E=VAR_ONE:hi,E=VAR_TWO:bye]
#
# You can read these values using %{ENV:VAR_NAME}e <- little "e" is not a typo
#
# Tangent:
# Note you can also read these env vars the same way, if you set them via SetEnvIf[NoCase]
# (It won't work to use SetEnv, which runs too early for mod_rewrite to pair with it.)
#
# Regex details:
# (?:) syntax means "match but don't store group in %1 backreference"
#      so (?:^|&) is simply the ^ beginning or an & delimiter
#      (the only 2 possibilities for the start of a qs param)
# ([^&]+) means 1 or more chars that are not an & delimiter

RewriteCond %{QUERY_STRING} (?:^|&)foo=([^&]+)
RewriteRule ^/before - [E=FOO_VAL:%1]

RewriteCond %{QUERY_STRING} (?:^|&)bar=([^&]+)
RewriteRule ^/before - [E=BAR_VAL:%1]

RewriteCond %{QUERY_STRING} (?:^|&)baz=([^&]+)
RewriteRule ^/before - [E=BAZ_VAL:%1]

RewriteRule ^/before /after?foo=%{FOO_VAL}e&bar=%{BAR_VAL}e&baz=%{BAZ_VAL}e&mood=happy [R=301,L]

P.S。这不是您的问题的复制/可粘贴解决方案,而是准确地显示如何来处理此类问题。武装这种理解,利用它作为你的榜样将是完全无足轻重的。 :)

答案 2 :(得分:0)

1)如果您只需要检查所有参数都在url中:

   RewriteCond %{QUERY_STRING} (^|&)category\=computers($|&)
   RewriteCond %{QUERY_STRING} (^|&)subcategory\=laptops($|&)
   RewriteCond %{QUERY_STRING} (^|&)product\=dell\-inspiron\-15($|&)
   RewriteRule ^$ http://store.example.com/computers/laptops/dell-inspiron-15/? [R=301,L]

2)如果您需要精确的参数集:

 RewriteCond %{QUERY_STRING} ^&*(?:category\=computers|subcategory\=laptops|product\=dell\-inspiron\-15)(?!.*&\1(?:&|$))(?:&+(category\=computers|subcategory\=laptops|product\=dell\-inspiron\-15)(?!.*&\1(?:&|$))){2}&*$
 RewriteRule ^$ http://store.example.com/computers/laptops/dell-inspiron-15/? [R=301,L] 

此规则由301 redirect generator

生成
相关问题