重写动态URL

dou*_*ood 7 apache .htaccess mod-rewrite

我试图将1个动态URL重写为另一个动态URL,如下所示;

/category?category=News to
/categorysearch/result/?q=news
Run Code Online (Sandbox Code Playgroud)

我想知道是否有人知道如何在htaccess中完成这项工作?

谢谢.

reg*_*ero 5

所以最终的EDITED解决方案是(对于您链接的.htaccess):

RewriteCond %{REQUEST_FILENAME} ethical [NC]
RewriteCond %{QUERY_STRING} (^|&|%26|%20)ethical(=|%3D)([^&]+) [NC]
RewriteRule .* /catalogsearch/result/?q=%3 [L,R]
Run Code Online (Sandbox Code Playgroud)

如果我使用当前问题中的"类别"术语:

RewriteCond %{REQUEST_FILENAME} category [NC]
RewriteCond %{QUERY_STRING} (^|&|%26|%20)category(=|%3D)([^&]+) [NC]
RewriteRule .* /categorysearch/result/?q=%3 [L,R]
Run Code Online (Sandbox Code Playgroud)

但第一个更清楚,类别这个词并不是随处可见.如果你想添加小写转换,我们甚至会做:

# outside of a Directory section
RewriteMap lowercase int:tolower
# in a Directory section (not a .htaccess)
RewriteCond %{REQUEST_FILENAME} category [NC]
RewriteCond %{QUERY_STRING} (^|&|%26|%20)category(=|%3D)([^&]+) [NC]
RewriteRule .* /catalogsearch/result/?q=${lowercase:%3} [L,R]
Run Code Online (Sandbox Code Playgroud)

但正如评论这最后一个与tolower将无法在工作的.htaccess -反正的.htaccess是坏的,真的,演出,你应该认真考虑设置了AllowOverride None和移动所有这些东西在一个虚拟主机.而像rewriteMaps这样的好东西不能用于.htaccess文件.

所以现在我将解释规则.首先,你的情况的主要问题是"?"之后的一切 是query_string,而不是请求的文件名.大多数rewriteRules尝试处理请求的文件名.所以我首先检查我们是否有针对性的问题文件名:

RewriteCond %{REQUEST_FILENAME} category [NC]
Run Code Online (Sandbox Code Playgroud)

然后我们将处理查询字符串(问号后面的所有内容).我们本可以编写一些非常简单的东西:

RewriteCond %{REQUEST_FILENAME} category [NC]
RewriteCond %{QUERY_STRING} ^category=(.+) [NC]
RewriteRule .* /catalogsearch/result/?q=${lowercase:%1} [L,R]
Run Code Online (Sandbox Code Playgroud)

为了捕获RewriteRule可用的变量%1之后的所有内容?category = 但QUERY_STRING参数有几个问题,让我们尝试一下它的乐趣:

  • 尚未对此参数执行url解码
  • category可能不是参数列表中的第一个参数
  • 它甚至可能不是最后一个(&foo = bar)
  • 你以前可以有一些空格

编辑:

我的第一个答案是:

RewriteCond %{REQUEST_FILENAME} category [NC]
RewriteCond %{QUERY_STRING} [^|&|%26|%20][category](=|%3D)([^&]+) [NC]
RewriteRule .* /catalogsearch/result/?q=${lowercase:%2} [L,R]
Run Code Online (Sandbox Code Playgroud)

通过[^|&|%26|%20]捕获事实它可能是起始参数或在&或空格之后的参数,%26是&urlencoded.

但这是错误的,感谢@mootinator评论我已经检查了一点,[类别]匹配'类别',但'atcatcategory'和这些字母的任何组合.

RewriteCond %{QUERY_STRING} category(=|%3D)([^&]+) [NC]
Run Code Online (Sandbox Code Playgroud)

匹配'category'参数,删除^允许将此参数放在任何位置.但这也会匹配一个名为的参数subcategory.所以第一个字母必须是空格或&(或查询字符串的开头).

这就是[^|&|%26|%20]我开始连锁OR和/或空间或者在urlencoded中的原因.但这也是错误的,^内部[]意味着否定.所以我们需要在这里使用匹配的括号:(^|&|%26|%20),现在它起作用,唯一的问题是参数的值现在是%3而不是%2

然后我们赶上(类别)的字,真正做到精确,我们其实应该抓住它以大写字母,小写字母和字母的urlencoded的版本后,信信较低和大写,像一个awfull [c|C|%43|%63][a|A|%61|%41][t|T|%74|...]to be continued-我也许应该用括号而不是括号,地狱,检查urlencoded字符列表在这里.

(=|%3D)urlencoded是否为"="字符.我本来可以使用,[=|%3D]%3D在这种情况下不匹配,我不明白为什么(mod_rewrite是一个奇怪的事情的土地).由于使用了第一个匹配的括号,我们必须使用%2变量而不是%1.

然后我们有好的([^&]+),这意味着什么,但不是'&'.

在这些条件之后我们应用RewriteRule.我们采取一切(这是.*)并将其重定向到/catalogsearch/result/?q=%2我们使用的地方%3而不是$1或者$3因为我们没有在rewriteRule上捕获任何内容但是在之前的条件上(%3是最后一个条件上的第三个捕获数据,所以它是([^&]+)).如果在rewriteRule中添加QSA标志([L,R,QSA]),您甚至可以获取最终查询字符串上的其他参数,以便:

ethical?bar=toto& ethical=Foo&zorglub=titi 
=> is redirected to 
catalogsearch/result/?q=foo&bar=toto&%2520ethical=Foo&zorglub=titi
Run Code Online (Sandbox Code Playgroud)

如果我玩一个小网址编码:

ethical?bar=toto%26 ethical%3DFoo&zorglub=titi 
=> is redirected to 
catalogsearch/result/?q=foo&bar=toto%2526%2520ethical%253DFoo&zorglub=titi
Run Code Online (Sandbox Code Playgroud)

但这不是游戏的结束,我会让你处理所有你想要的urlencoding问题,你想要检测Foo值的所有变化,并将它们与tolower混合(这里它已经坏了).您甚至可能在参数或额外属性中没有编码网址的问题,但这很有趣:-)