如何使用mod_rewrite避免链重定向?

时间:2012-12-28 20:40:22

标签: apache .htaccess mod-rewrite redirect

基本上我正在我的网站上工作,对SEO很友好。我想实现以下目标:

  • 将网址重写为漂亮网址
  • 删除多个斜杠(例如example.com/////something///example.com/something/
  • 将www版本重定向到非www版本。
  • 隐藏所有网址的index.php文件
  • 从旧版(/?id=something/重定向到新网址/something/

我想出了这个.htaccess代码:

RewriteCond %{THE_REQUEST} //
RewriteRule .* $0 [R=301]

RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteCond %{QUERY_STRING} ^id=([a-z0-9\/-]+)
RewriteRule ^(.*)$ http://example.com/%1? [R=301]

RewriteRule ^index.php(.*)$ /$1 [R=301]
RewriteRule ^([a-z0-9\/-]+)$ /?id=$1 [L] 

......虽然它有效但它有副作用:链重定向,例如。 example.com/?id=something////// - > example.com/something////// - > example.com/something/

那么有没有办法重写或修改这段代码,所以它只会重定向一次到网址的首选版本?

2 个答案:

答案 0 :(得分:1)

试着解释你想要的东西,让我们看一下你问题中的规则:

.1无法理解这个目的:

RewriteCond %{THE_REQUEST} //
RewriteRule .* $0 [R=301]

.2您的问题中的此规则集会删除www并将查询字符串?id=val转换为/val,但仅当传入的URI具有www并且存在必须满足两个条件的查询字符串:

RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteCond %{QUERY_STRING} ^id=([a-z0-9\/-]+)
RewriteRule ^(.*)$ http://example.com/%1? [R=301]

.3这条规则

RewriteRule ^index.php(.*)$ /$1 [R=301]

隐藏index.php,但仅限于它位于根目录中。例如:

http://www.example.com/index.php?id=val

当它在子目录中时不起作用。例如:

http://www.example.com/folder/index.php?id=val

.4无法理解这个目的:

RewriteRule ^([a-z0-9\/-]+)$ /?id=$1 [L]

我建议这样做:

RewriteEngine On
RewriteBase /

#Redirects all www to non-www
RewriteCond %{HTTP_HOST} www\.example\.com$ [NC]
RewriteRule ^(.*)/?$ http://example.com/$1 [R=301,L]

#Hides "index.php" keeping the query if present
RewriteRule ^(.*)/index\.php$ $1/ [R=301,QSA,L]

#Converts query string `?id=val` to `/val`
RewriteCond %{QUERY_STRING} id=([^/]+)
RewriteRule .* /%1? [R=301,L]

答案 1 :(得分:1)

记住蜘蛛会在几个月后“适应”正确的新结构,这个问题可能最终会比最初看起来严重得多。您可以将所有.htaccess代码保留在原位,因为它知道它始终存在以纠正任何“旧”引用,但实际上几乎不会实际使用。

我从来没有找到一种简单的方法来避免在将某个网址“固定”为某种规范形式时多次往返客户端。 mod_rewrite似乎更侧重于“本地”重定向情况,其中客户端不知道它返回的内容来自与URL隐含的完全匹配的文件结构。

可能可能在本地保存所有URL mod,然后通过在新创建的“环境”变量中设置所有内容,只激发一次到客户端的往返,一次性提供所有URL更正然后在最后问基本上“有什么改变?”然而,这样做显然是冗长的,相当笨拙且非常容易出错,并且从未成为“推荐技术”。