13

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

  1. ?category=计算机
  2. &subcategory=笔记本电脑
  3. &product=戴尔灵越-15

我需要 301 将此 URL 重定向到其友好版本:

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]
4

3 回答 3

18

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

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]

为避免ORand 双重条件,您可以使用

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.

于 2013-01-13T21:32:56.207 回答
3

我对这种事情采取了一种稍微不同的方法,利用由 mod_rewrite 设置和读取的 ENV VAR。我发现像这样按名称引用反向引用更具可读性/可维护性,并且这些 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]

PS这不是您问题的复制/粘贴解决方案,而是准确显示如何处理此类问题。有了这种理解,将其用于您的示例将完全是微不足道的。:)

于 2014-10-17T21:47:09.697 回答
1

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 重定向生成器生成

于 2019-09-17T07:38:36.893 回答