重写动态URL

时间:2011-10-09 12:38:18

标签: apache .htaccess mod-rewrite

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

/category?category=News to
/categorysearch/result/?q=news

我想知道是否有人知道如何在htaccess中做到这一点?

感谢。

3 个答案:

答案 0 :(得分:5)

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

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

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

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

但第一个更清楚,单词类别并未随处使用。如果你想添加小写转换,我们甚至会这样做:

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

但是评论最后一个与tolower无法在.htaccess中工作 - 无论如何.htaccess很糟糕,真的,对于表演,你应该考虑设置AllowOverride None并移动所有这些虚拟主机中的东西。诸如 rewriteMaps 之类的好东西不适用于.htaccess文件。

所以现在我解释规则。首先,您遇到的主要问题是“?”之后的所有内容都是 query_string ,而不是请求的文件名。大多数rewriteRules尝试处理请求的文件名。所以我首先检查我们是否有针对性的问题文件名:

RewriteCond %{REQUEST_FILENAME} category [NC]

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

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

要捕获之后的所有内容?category =在可用于RewriteRule的变量%1中。但是QUERY_STRING参数有几个问题,让我们试着用它来获得一些乐趣:

  • 尚未对此参数进行网址解码
  • 类别可能不是参数列表中的第一个参数
  • 它甚至可能不是最后一个(& foo = bar)
  • 你可以在
  • 之前有一些空格

<强> EDITED

我的第一个答案是:

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

[^|&|%26|%20]抓住事实,它可能是起始参数或&amp;之后的参数。或空格,%26是&amp; urlencoded的。

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

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

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

这就是[^|&|%26|%20]的原因,这意味着我可以开始使用OR&amp; amp;或空间或&amp;在urlencoded。但那也是错误^[]意味着否定。所以我们需要在这里使用匹配的括号:(^|&|%26|%20),现在它可以工作,唯一的问题是参数的值现在是%3而不是%2

然后我们抓住(类别)单词,确切地说我们应该事实上用大写字母,小写字母和大写字母的urlencoded版本一字母写下它,就像一个可怕的[c|C|%43|%63][a|A|%61|%41][t|T|%74|...]to be continued - 我应该使用括号而不是括号,地狱,检查urlencoded characters list here

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

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

在这些条件之后我们应用RewriteRule。我们接受所有内容(这是.*)并将其重定向到我们使用/catalogsearch/result/?q=%2而不是%3$1的{​​{1}},因为我们没有捕获任何内容rewriteRule但在之前的条件($3是最后一个条件的第三个捕获数据,因此它是%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

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

答案 1 :(得分:0)

根据您要做的事情以及具体事项的具体情况,有两种选择。

第一个是Rob W的解决方案,它应该将用户从/category?category=News重定向到/categorysearch/result/?q=News

如果看起来您的网址区分大小写,那么您可能需要查看以下PHP脚本:

$matches = array();
if( preg_match( "/^/category\?category=(.+)/", $_SERVER['REQUEST_URI'], $matches ) ) {
    header( 'Location: http://' . $_SERVER['HTTP_HOST'] . '/categorysearch/result/?q= . strtolower($matches[1]) );
}
else {
    //ERROR HANDLING
}

一旦确定,您可以使用如下规则来使用完全小写的参数重定向。

RewriteRule ^category\?category=(.+)$ redirect.php [L]

总之,此解决方案会将/category?category=News重定向到/categorysearch/result/?q=news

答案 2 :(得分:-1)

我认为

RewriteRule ^/category?category=(.*) /categorysearch/result/?q=news

会这样做。