网址重定向及重写的方法
02.27 22:16:27发布
离殇
正如我们刚刚提到的,实现重定向有许多可能的方法,在Apache网络服务器上(通常作为操作系统呈现在运行UNIX或Linux的机器中),我们能够在一个名为.htacess的标准文件中使用Redirect和RedirectMatch指令轻松地进行重定向。另外,你还可以使用一些称为rewire rules的高级指令,使用称为mod_rewrite的Apache组件进行重定向,我们稍后将对此进行讲解。
在运行Microsoft IIS的网络服务器中,提供了多种执行重定向的方法。正如我们在“IIS Redirects-301,302”中所描述的那样,最基本的方法是使用IIS控制台。具有IIS服务器的用户还可以使用一个带有指令的文本文件,假设他们使用ISAPI插件,如ISAPI_Rewrite,这一脚本语言具有与Apache mod_rewrite组件相类似的功能。
许多程序员会使用其他的技巧执行重定向,如直接在程序语言中运行,如Perl、PHP、ASP和JavaScript。如果以这种形式运行重定向,那么程序员必须确保网络服务器返回的HTTP状态码是301。你可以使用Firefox插件Live HTTP Headers、Chrome扩展或基于网络的服务器标题检测工具检查返回的标题。
另外一种执行重定向的方法是在页面层面通过使用元refresh标签执行的,该标签看起来像下面这样:
在content部分的第一个参数5表示网络服务器在将用户重定向至指定页面前需等待的时间,发布者可能会使用这一方法展示页面,让用户知道他们将被重定向至一个与其目标页面不同的页面。
但问题是,大部分元新标签都会被看作302重定向,唯一的例外情况是你将重定向延迟设置为0秒。你需要放弃能够告知用户你在进行重定向的帮助页面,但搜索引擎可能会把它看作301重定向(为安全起见,最好的做法是尽量使用301重定向)。
网址重写和重定向的mod_rewrite和ISAPI_Rewrite
对于该话题,有大量的内容可写,本书仅呈现一部分。下面的描述仅是一个简单的描述,旨在帮助一些包括网络设计者和网站管理者在内的专业人员了解重写和重定向是如何运行的。要跳过这一技术性话题,“如何在无循环的情况下重定向主页索引文件”。
Apache的mod_rewrite及Microsoft IIS服务器的ISAPI_Rewrite均为网址重写提供了很好的途径,使用这些工具的原因如下:
·你已经改变了网站中的网址结构,所以内容也从一个位置移动到了另一个位置,当你出于某些原因而改变CMS或网站体制时,便会出现这种情况。
·你想将一些不适应搜索引擎的网址替换为搜索引擎友好型网址。
如果你将Apache作为自己的网络服务器,那么你会在.htaccess文件或Apache配置文件中放置一个称为rewrite rules的指令(如sites_conf目录中的httpd.conf或站点特定的配置文件)。同样地,如果你使用的是IIS服务器,那么你会使用一个ISAPI插件,如ISAPI_Rewrite,而将规则放在httpd.ini配置文件中。
需要注意的是,ISAPI_Rewrite和mod_rewrite的规则可能有所不同,而下面的讨论主要围绕mod_rewrite展开,你的.htaccess文件可能这样开头:
如果你要将rewrite添加到服务器配置文件中,则需要删除第二行,因为只有.htaccess支持RewriteBase。我们在这里使用的是RewriteBase,这样你便不需要在所有规则的开头都输入^/,而只要输入^即可(我们稍后会介绍正则表达式)。
完成这一步之后,重写规则便会被运行,或许你要求在不改变用户浏览器位置栏的网址和不重新编码get_product.php脚本的情况下,http://www.yourdomain.com/products/123格式下的产品页面网址能够显示http://www.yourdomain.com/get_product.php?id=123中的内容。当然,这不能取代所有出现在网站页面链接中的动态网址,那属于另一个话题范围了。你可以使用一个简单的重写规则实现第一部分的要求,类似于:
这个例子告诉网络服务器所有进入/product/目录的搜索请求都应被映射到/get_product.php请求,同时使用/product/的子文件夹作为PHP脚本的参数。
^符号表示域名网址的开头,$符号表示网址的结尾,[0-9]表示数位,而紧随其后的+符号表示数位的一次或多次出现。同样地,/后面的?表示斜杠符号出现0次或1次,()符号会记住所有括号内的内容,之后,你可以使用$1访问缓存中的内容(如,第一组括号内的全部内容)。不足为奇的是,如果规则中包含第二组括号,那么你可以使用$2访问第二组括号的所有内容,依次类推。[L]标志保存在服务器进程中,指示重写引擎一旦匹配该规则便停止运行,否则,所有剩下的规则就会被运行。
下面是一个稍微复杂点的例子,http://www.yourdo-main.com/webapp/wcs/stores/servlet/ProductDisplay?storeId=10001&catalogId=10001&langId=-1&categoryID=4&productID=123格式的网址将被重写为http://www.yourdomain.com/4/123.htm:
[^/]表示除了斜线之外的任一符号,这是因为^在方括号内被理解为不。[QSA]标志是表示你不希望搜索请求字符串被缓存(就像你不希望追踪参数被保存一样)。
要撰写优质的重写规则,你需要变成一个模式匹配大师(这是描述正则表达式功能的另一种方式),下面列举一些最重要的特殊符号及重写引擎对这些符号的解读。
*:当前字符匹配0次或n次。
+:当前字符匹配1次或n次。
?:当前字符出现0次或1次。
^:字符串的开始。
$:字符串的结尾。
.:任意符号(如作为通配符)。
\:“避开”后面的字符,如\.表示点不是一个通配符而是一个实际的字符。
^:在[]括号内表示非,例如,[^/]表示非斜杠。
在正则表达式中,轻易便会犯下错误,一些常见的、导致无意子字符串匹配的错误包括如下:
·在应该使用.+的地方使用了.*(因为.*什么都不匹配)。
·没有使用反斜杠换码一个你不想表达的特殊符号,因为当你指定.代替\.时,你确实指的是点这个符号而不是任意字符(因此,default.htm会匹配defaultthtm,而default\.htm会只匹配default.htm)。
·在开头或结尾通过隐含方式确定的前提下,省略^或$(因此,default\.htm会匹配mydefault.html,而^default\.htm$只匹配default.htm)。
·使用“贪婪”表达式,匹配所有出现的次数而不是在第一次出现之后停止。
·诠释“贪婪”最简单的方式是给出一个例子:
该表达式将重定向所有从http://www.yourdomain.com/blah/index.html向http://www.yourdomain.com/blah/的请求,这可能并不是其本意,但为什么会出现这种情况?因为.*会在/?看到斜线符号之前将其采集,谢天谢地,我们有一个简单的解决方案。使用[^或.*?代替.*来进行匹配,例如,使用^(.*?)/?代替^(.*)/?,或使用[^/]+/[^/]代替.*/.*。
因此,要改正上述规则,你可以使用以下表达式:
为什么不用下面这个呢?
它比较有限,因为它只能匹配包含一个目录的网址,而包含多个子目录的网址则不能匹配,如http://www.yourdomain.com/store/cheese/swiss/wheel/index.html。
你可能也想过,测试或调试应是网址重写中比较重要的部分,当你进行调试时,RewriteLog和RewriteLogLevel指令便是你最好的伙伴!将RewriteLogLevel设置为4或以上值,然后查看重写引擎在诠释你的规则时会做什么。
顺便说一下,在后面几个例子中的[R=301]标志——你可能也猜到了——是告诉重写引擎进行301重定向而不是标准的重写。
还有另外一个与RewriteRule连用的指令,称为RewriteCond。你可能会使用RewriteCond匹配搜索请求字符串中的内容、域名或其他未出现在域名和网址问号之间的元素(这正是RewriteCond所关注的内容)。
需要注意的是,RewriteRule和RewriteCond都不能访问网址锚节点中的内容——即#后面的内容,因为该部分内容本质上是被浏览器所用的,是不会被作为请求的一部分发送到服务器的。下面的RewriteCond案例是在其允许执行重写规则之前,寻找一个正面匹配的主机名:
注意正则表达式开头的感叹号,重写引擎把它理解为非。
对于除了http://www.yourdomain.com之外的任何一个主机名来说,301重定向相当于www子域名中的标准网址。[NC]标志使重写条件区分大小写。你可能会问,保存搜索请求字符串的[QSA]标志去哪儿了?重定向不需要它,它是隐含的。
如果你不希望搜索请求字符串留存在含有重定向的重写规则中,那么可以在规则中的目标网址末端添加一个问号,类似于:
为什么不用^yourdomain\.com$?想一下:
该表达式不匹配typo域名,如yourdoamin.com,DNS服务器和虚拟主机将被设置为响应typo域名(假设错误拼写是一个你注册和拥有的域名)。
在什么情况下,你会希望从重定向的网址中省略搜索请求字符串,如我们在上面两个例子中那样呢?当会话ID或追踪参数(如source=banner_ad1)需要被放弃时。没有必要在重定向之后保留追踪参数(因为包含源代码的原始网址在被访问之后,会被记录到访问日志文件中),而且从规范化角度来看,你也没必要那样做。如果你希望从重定向的网址中删除追踪参数,但同时又想保留搜索请求字符串中的其他参数,你应该怎么做呢?下面是针对静态网址的做法:
而对于动态网址:
在重定向用户之前,需要用cookie做一些奇妙的事情吗?调用一个跟踪用户的脚本,然后301重定向该用户至标准网址:
注意上述代码中没有[R=301]标志,这是故意的,因为没有必要将该脚本展示给用户,该脚本完成它的使命之后,使用重写,让它自己发送301重定向。
其他值得用重写规则和[R=301]标志修改的标准化问题包括:搜索引擎索引HTTPS网址下的在线目录页面时及网址漏掉一个本应有的尾斜杠时。首先,HTTPS解决方案是:
需要注意的是,如果你的安全服务器与主服务器分离,那么你可以跳过RewriteCond行。
现在添加尾斜杠:
完成网址重写工作,将动态网址替换成静态网址之后,你可能想逐步淘汰动态网址,你可能会替代网站中所有出现的遗留网址,也可能会使用301重定向遗留的动态网址至其静态对应页面。这样一来,所有指向废弃网址的导入链接便不会再引导搜索爬虫和人类用户进入正确的新网址——因此,确保新的网址是被索引、引用、链接和标记的,而将原有网址从索引中删除。通常来讲,下面是你的做法:
不过,如果你不小心,便可能会陷入无限循环重定向的怪圈,避免该局面的一个应急方案是在重写的目标网址中添加一个无意义的参数,而且要确保这个无意义的参数不会在你进行重定向之前出现,具体是:
需要注意的是,该案例使用了两个堆在一起的RedirectCond行,在同一区块中列出的所有重定向条件都是“ANDed”(并列)一起的,如果你希望条件是“Ored”,那么你需要使用[OR]标志。
最多设置5个标签!
正如我们刚刚提到的,实现重定向有许多可能的方法,在Apache网络服务器上(通常作为操作系统呈现在运行UNIX或Linux的机器中),我们能够在一个名为.htacess的标准文件中使用Redirect和RedirectMatch指令轻松地进行重定向。另外,你还可以使用一些称为rewire rules的高级指令,使用称为mod_rewrite的Apache组件进行重定向,我们稍后将对此进行讲解。
在运行Microsoft IIS的网络服务器中,提供了多种执行重定向的方法。正如我们在“IIS Redirects-301,302”中所描述的那样,最基本的方法是使用IIS控制台。具有IIS服务器的用户还可以使用一个带有指令的文本文件,假设他们使用ISAPI插件,如ISAPI_Rewrite,这一脚本语言具有与Apache mod_rewrite组件相类似的功能。
许多程序员会使用其他的技巧执行重定向,如直接在程序语言中运行,如Perl、PHP、ASP和JavaScript。如果以这种形式运行重定向,那么程序员必须确保网络服务器返回的HTTP状态码是301。你可以使用Firefox插件Live HTTP Headers、Chrome扩展或基于网络的服务器标题检测工具检查返回的标题。
另外一种执行重定向的方法是在页面层面通过使用元refresh标签执行的,该标签看起来像下面这样:
在content部分的第一个参数5表示网络服务器在将用户重定向至指定页面前需等待的时间,发布者可能会使用这一方法展示页面,让用户知道他们将被重定向至一个与其目标页面不同的页面。
但问题是,大部分元新标签都会被看作302重定向,唯一的例外情况是你将重定向延迟设置为0秒。你需要放弃能够告知用户你在进行重定向的帮助页面,但搜索引擎可能会把它看作301重定向(为安全起见,最好的做法是尽量使用301重定向)。
网址重写和重定向的mod_rewrite和ISAPI_Rewrite
对于该话题,有大量的内容可写,本书仅呈现一部分。下面的描述仅是一个简单的描述,旨在帮助一些包括网络设计者和网站管理者在内的专业人员了解重写和重定向是如何运行的。要跳过这一技术性话题,“如何在无循环的情况下重定向主页索引文件”。
Apache的mod_rewrite及Microsoft IIS服务器的ISAPI_Rewrite均为网址重写提供了很好的途径,使用这些工具的原因如下:
·你已经改变了网站中的网址结构,所以内容也从一个位置移动到了另一个位置,当你出于某些原因而改变CMS或网站体制时,便会出现这种情况。
·你想将一些不适应搜索引擎的网址替换为搜索引擎友好型网址。
如果你将Apache作为自己的网络服务器,那么你会在.htaccess文件或Apache配置文件中放置一个称为rewrite rules的指令(如sites_conf目录中的httpd.conf或站点特定的配置文件)。同样地,如果你使用的是IIS服务器,那么你会使用一个ISAPI插件,如ISAPI_Rewrite,而将规则放在httpd.ini配置文件中。
需要注意的是,ISAPI_Rewrite和mod_rewrite的规则可能有所不同,而下面的讨论主要围绕mod_rewrite展开,你的.htaccess文件可能这样开头:
如果你要将rewrite添加到服务器配置文件中,则需要删除第二行,因为只有.htaccess支持RewriteBase。我们在这里使用的是RewriteBase,这样你便不需要在所有规则的开头都输入^/,而只要输入^即可(我们稍后会介绍正则表达式)。
完成这一步之后,重写规则便会被运行,或许你要求在不改变用户浏览器位置栏的网址和不重新编码get_product.php脚本的情况下,http://www.yourdomain.com/products/123格式下的产品页面网址能够显示http://www.yourdomain.com/get_product.php?id=123中的内容。当然,这不能取代所有出现在网站页面链接中的动态网址,那属于另一个话题范围了。你可以使用一个简单的重写规则实现第一部分的要求,类似于:
这个例子告诉网络服务器所有进入/product/目录的搜索请求都应被映射到/get_product.php请求,同时使用/product/的子文件夹作为PHP脚本的参数。
^符号表示域名网址的开头,$符号表示网址的结尾,[0-9]表示数位,而紧随其后的+符号表示数位的一次或多次出现。同样地,/后面的?表示斜杠符号出现0次或1次,()符号会记住所有括号内的内容,之后,你可以使用$1访问缓存中的内容(如,第一组括号内的全部内容)。不足为奇的是,如果规则中包含第二组括号,那么你可以使用$2访问第二组括号的所有内容,依次类推。[L]标志保存在服务器进程中,指示重写引擎一旦匹配该规则便停止运行,否则,所有剩下的规则就会被运行。
下面是一个稍微复杂点的例子,http://www.yourdo-main.com/webapp/wcs/stores/servlet/ProductDisplay?storeId=10001&catalogId=10001&langId=-1&categoryID=4&productID=123格式的网址将被重写为http://www.yourdomain.com/4/123.htm:
[^/]表示除了斜线之外的任一符号,这是因为^在方括号内被理解为不。[QSA]标志是表示你不希望搜索请求字符串被缓存(就像你不希望追踪参数被保存一样)。
要撰写优质的重写规则,你需要变成一个模式匹配大师(这是描述正则表达式功能的另一种方式),下面列举一些最重要的特殊符号及重写引擎对这些符号的解读。
*:当前字符匹配0次或n次。
+:当前字符匹配1次或n次。
?:当前字符出现0次或1次。
^:字符串的开始。
$:字符串的结尾。
.:任意符号(如作为通配符)。
\:“避开”后面的字符,如\.表示点不是一个通配符而是一个实际的字符。
^:在[]括号内表示非,例如,[^/]表示非斜杠。
在正则表达式中,轻易便会犯下错误,一些常见的、导致无意子字符串匹配的错误包括如下:
·在应该使用.+的地方使用了.*(因为.*什么都不匹配)。
·没有使用反斜杠换码一个你不想表达的特殊符号,因为当你指定.代替\.时,你确实指的是点这个符号而不是任意字符(因此,default.htm会匹配defaultthtm,而default\.htm会只匹配default.htm)。
·在开头或结尾通过隐含方式确定的前提下,省略^或$(因此,default\.htm会匹配mydefault.html,而^default\.htm$只匹配default.htm)。
·使用“贪婪”表达式,匹配所有出现的次数而不是在第一次出现之后停止。
·诠释“贪婪”最简单的方式是给出一个例子:
该表达式将重定向所有从http://www.yourdomain.com/blah/index.html向http://www.yourdomain.com/blah/的请求,这可能并不是其本意,但为什么会出现这种情况?因为.*会在/?看到斜线符号之前将其采集,谢天谢地,我们有一个简单的解决方案。使用[^或.*?代替.*来进行匹配,例如,使用^(.*?)/?代替^(.*)/?,或使用[^/]+/[^/]代替.*/.*。
因此,要改正上述规则,你可以使用以下表达式:
为什么不用下面这个呢?
它比较有限,因为它只能匹配包含一个目录的网址,而包含多个子目录的网址则不能匹配,如http://www.yourdomain.com/store/cheese/swiss/wheel/index.html。
你可能也想过,测试或调试应是网址重写中比较重要的部分,当你进行调试时,RewriteLog和RewriteLogLevel指令便是你最好的伙伴!将RewriteLogLevel设置为4或以上值,然后查看重写引擎在诠释你的规则时会做什么。
顺便说一下,在后面几个例子中的[R=301]标志——你可能也猜到了——是告诉重写引擎进行301重定向而不是标准的重写。
还有另外一个与RewriteRule连用的指令,称为RewriteCond。你可能会使用RewriteCond匹配搜索请求字符串中的内容、域名或其他未出现在域名和网址问号之间的元素(这正是RewriteCond所关注的内容)。
需要注意的是,RewriteRule和RewriteCond都不能访问网址锚节点中的内容——即#后面的内容,因为该部分内容本质上是被浏览器所用的,是不会被作为请求的一部分发送到服务器的。下面的RewriteCond案例是在其允许执行重写规则之前,寻找一个正面匹配的主机名:
注意正则表达式开头的感叹号,重写引擎把它理解为非。
对于除了http://www.yourdomain.com之外的任何一个主机名来说,301重定向相当于www子域名中的标准网址。[NC]标志使重写条件区分大小写。你可能会问,保存搜索请求字符串的[QSA]标志去哪儿了?重定向不需要它,它是隐含的。
如果你不希望搜索请求字符串留存在含有重定向的重写规则中,那么可以在规则中的目标网址末端添加一个问号,类似于:
为什么不用^yourdomain\.com$?想一下:
该表达式不匹配typo域名,如yourdoamin.com,DNS服务器和虚拟主机将被设置为响应typo域名(假设错误拼写是一个你注册和拥有的域名)。
在什么情况下,你会希望从重定向的网址中省略搜索请求字符串,如我们在上面两个例子中那样呢?当会话ID或追踪参数(如source=banner_ad1)需要被放弃时。没有必要在重定向之后保留追踪参数(因为包含源代码的原始网址在被访问之后,会被记录到访问日志文件中),而且从规范化角度来看,你也没必要那样做。如果你希望从重定向的网址中删除追踪参数,但同时又想保留搜索请求字符串中的其他参数,你应该怎么做呢?下面是针对静态网址的做法:
而对于动态网址:
在重定向用户之前,需要用cookie做一些奇妙的事情吗?调用一个跟踪用户的脚本,然后301重定向该用户至标准网址:
注意上述代码中没有[R=301]标志,这是故意的,因为没有必要将该脚本展示给用户,该脚本完成它的使命之后,使用重写,让它自己发送301重定向。
其他值得用重写规则和[R=301]标志修改的标准化问题包括:搜索引擎索引HTTPS网址下的在线目录页面时及网址漏掉一个本应有的尾斜杠时。首先,HTTPS解决方案是:
需要注意的是,如果你的安全服务器与主服务器分离,那么你可以跳过RewriteCond行。
现在添加尾斜杠:
完成网址重写工作,将动态网址替换成静态网址之后,你可能想逐步淘汰动态网址,你可能会替代网站中所有出现的遗留网址,也可能会使用301重定向遗留的动态网址至其静态对应页面。这样一来,所有指向废弃网址的导入链接便不会再引导搜索爬虫和人类用户进入正确的新网址——因此,确保新的网址是被索引、引用、链接和标记的,而将原有网址从索引中删除。通常来讲,下面是你的做法:
不过,如果你不小心,便可能会陷入无限循环重定向的怪圈,避免该局面的一个应急方案是在重写的目标网址中添加一个无意义的参数,而且要确保这个无意义的参数不会在你进行重定向之前出现,具体是:
需要注意的是,该案例使用了两个堆在一起的RedirectCond行,在同一区块中列出的所有重定向条件都是“ANDed”(并列)一起的,如果你希望条件是“Ored”,那么你需要使用[OR]标志。
一周热门 更多>