23 November 2005
This post may be outdated due to it was written on 2005. The links may be broken. The code may be not working anymore. Leave comments if needed.
这次讲 modperl 的PerlTransHandler,主要的作用是 url rewrite

PerlTransHandler

前面 modperl 服务器的运行阶段和句柄 中讲过 PerlTransHandler 主要用于处理 URI
如果你用过 mod_rewrite 的话,发现这个 handler 比 mod_rewrite 更实用。

假设我们为了对搜索引擎友好,将动态的 URL 地址类如

http://www.fayland.org/cgi-bin/topic.cgi?id=44
http://www.fayland.org/cgi-bin/topic.cgi?id=44&type=print
分别转为对搜索引擎更友好的静态地址如
http://www.fayland.org/topic/44
http://www.fayland.org/topic/print/44
我没用 mod_rewrite 转过,但是试验过 PerlTransHandler:
package MyApache2::RewriteTopic;

use strict;
use warnings;

use Apache2::RequestRec ();

use Apache2::Const -compile => qw(DECLINED);

sub handler {
   my $r = shift;

   # for http://www.fayland.org/topic/44
   if ($r->uri =~ m|^/topic/(\d+)/?|) {
       $r->uri("/cgi-bin/topic.cgi");
       $r->args("id=$1");
   }
   # for http://www.fayland.org/topic/print/44
   if ($r->uri =~ m|^/topic/([a-z]+)/(\d+)/?|) {
       $r->uri("/cgi-bin/topic.cgi");
       $r->args("id=$2&type=$1");
   }

   return Apache2::Const::DECLINED;
}

1;

在 perl.conf 或 httpd.conf 增加:
PerlTransHandler +MyApache2::RewriteTopic
或者是
PerlModule MyApache2::RewriteTopic
PerlTransHandler MyApache2::RewriteTopic
两者是等同的。

    其间值得提提的有一下几点:
  • $r->uri 设定转向的 URI
  • $r->args 设定参数/parameters 这些参数可以用 CGI 的 param 来获取
  • Apache2::Const::DECLINED
    我在前面的那文章里讲过 PerlTransHandler 的类型是 RUN_FIRST,所以当我们返回 DECLINED 时,接下来的 hook 也能被执行。

    比如我们另外定义了一个 MyApache2::RewriteView 这个模块唯一不同的就是把 topic 改为 view, 且在 perl.conf 里增加 PerlTransHandler +MyApache2::RewriteTopic +MyApache2::RewriteView

    修改完后当我们碰到类如 http://www.fayland.org/view/77 时,虽然 MyApache2::RewriteTopic 不满足,但是由于它返回的是 Apache2::Const::DECLINED, 所以会接下来继续下面的 MyApache2::RewriteView。
    而如果 RewriteTopic 返回的是 Apache2::Const::OK, 那接下来的 MyApache2::RewriteView 就不会再继续了。

另外注意将 $r->uri("/cgi-bin/topic.cgi"); $r->args("id=$1"); 放到 if 里面,否则将 PerlTransHandler +MyApache2::RewriteTopic 放到某个 Location 里。
要不弄成全局,就将所有的 URI 都转向 topic.cgi 了。:)



blog comments powered by Disqus