stas 2002/08/30 10:24:49 Modified: src/docs/2.0/user/handlers handlers.pod Log: PerlTypeHandler, PerlFixupHandler, PerlResponseHandler examples Revision Changes Path 1.17 +176 -6 modperl-docs/src/docs/2.0/user/handlers/handlers.pod Index: handlers.pod =================================================================== RCS file: /home/cvs/modperl-docs/src/docs/2.0/user/handlers/handlers.pod,v retrieving revision 1.16 retrieving revision 1.17 diff -u -r1.16 -r1.17 --- handlers.pod 28 Aug 2002 18:05:42 -0000 1.16 +++ handlers.pod 30 Aug 2002 17:24:49 -0000 1.17 @@ -1536,7 +1536,32 @@ The handler's configuration scope is C<L<DIR|docs::2.0::user::config::config/item_DIR>>. -Example: +The most important thing to remember when overriding the default +I<type_checker> handler, which is usually the mod_mime handler, is +that you have to set the handler that will take care of the response +phase and the response callback function or the code won't +work. mod_mime does that based on C<SetHandler> and C<AddHandler> +directives, and file extensions. So if you want the content handler to +be run by mod_perl, set either: + + $r->handler('perl-script'); + $r->set_handlers(PerlResponseHandler => \&handler); + +or: + + $r->handler('modperl'); + $r->set_handlers(PerlResponseHandler => \&handler); + +depending on which type of response handler is wanted. + +Writing a C<PerlTypeHandler> handler which sets the content-type value +and returns C<Apache::DECLINED> so that the default handler will do +the rest of the work, is not a good idea, because mod_mime will +probably override this and other settings. + +Therefore it's the easiest to leave this stage alone and do any +desired settings in the I<fixups> phase. + @@ -1553,7 +1578,102 @@ The handler's configuration scope is C<L<DIR|docs::2.0::user::config::config/item_DIR>>. -Example: +The following fixup handler example tells Apache at run time which +handler and callback should be used to process the request based on +the file extension of the request's URI. + + file:MyApache/FileExtDispatch.pm + -------------------------------- + package MyApache::FileExtDispatch; + + use Apache::Const -compile => 'OK'; + + use constant HANDLER => 0; + use constant CALLBACK => 1; + + my %exts = ( + cgi => ['perl-script', \&cgi_handler], + pl => ['modperl', \&pl_handler ], + tt => ['perl-script', \&tt_handler ], + txt => ['default-handler', undef ], + ); + + sub handler { + my $r = shift; + + my ($ext) = $r->uri =~ /\.(\w+)$/; + $ext = 'txt' unless defined $ext and exists $exts{$ext}; + + $r->handler($exts{$ext}->[HANDLER]); + + if (defined $exts{$ext}->[CALLBACK]) { + $r->set_handlers(PerlHandler => $exts{$ext}->[CALLBACK]); + } + + return Apache::OK; + } + + sub cgi_handler { content_handler($_[0], 'cgi') } + sub pl_handler { content_handler($_[0], 'pl') } + sub tt_handler { content_handler($_[0], 'tt') } + + sub content_handler { + my($r, $type) = @_; + + $r->content_type('text/plain'); + $r->print("A handler of type '$type' was called"); + + return Apache::OK; + } + + 1; + +In the example we have used the following mapping. + + my %exts = ( + cgi => ['perl-script', \&cgi_handler], + pl => ['modperl', \&pl_handler ], + tt => ['perl-script', \&tt_handler ], + txt => ['default-handler', undef ], + ); + +So that I<.cgi> requests will be handled by the C<perl-script> handler +and the C<cgi_handler()> callback, I<.pl> requests by C<modperl> and +C<pl_handler()>, I<.tt> (template toolkit) by C<perl-script> and the +C<tt_handler()>, finally I<.txt> request by the C<default-handler> +handler, which requires no callback. + +Moreover the handler assumes that if the request's URI has no file +extension or it does, but it's not in its mapping, the +C<default-handler> will be used, as if the I<txt> extension was used. + +After doing the mapping, the handler assigns the handler: + + $r->handler($exts{$ext}->[HANDLER]); + +and the callback if needed: + + if (defined $exts{$ext}->[CALLBACK]) { + $r->set_handlers(PerlHandler => $exts{$ext}->[CALLBACK]); + } + +In this simple example the callback functions don't do much but +calling the same content handler which simply prints the name of the +extension if handled by mod_perl, otherwise Apache will serve the +other files using the default handler. In real world you will use +callbacks to real content handlers that do real things. + +Here is how this handler is configured: + + Alias /dispatch/ /home/httpd/dispatch/ + <Location /dispatch/> + PerlFixupHandler MyApache::FileExtDispatch + </Location> + +Notice that there is no need to specify anything, but the fixup +handler. It applies the rest of the settings dynamically at run-time. + + =head2 PerlResponseHandler @@ -1570,16 +1690,66 @@ PerlResponseHandler Apache::Registry </Location> -C<SetHandler> tells Apache that mod_perl is going to handle the -response generation. C<PerlResponseHandler> tells mod_perl which -handler is going to do the job. +C<SetHandler> set to +L<C<perl-script>|docs::2.0::user::config::config/perl_script> or +L<C<modperl>|docs::2.0::user::config::config/modperl> tells Apache +that mod_perl is going to handle the response +generation. C<PerlResponseHandler> tells mod_perl which callback is +going to do the job. This phase is of type C<L<RUN_FIRST|/item_RUN_FIRST>>. The handler's configuration scope is C<L<DIR|docs::2.0::user::config::config/item_DIR>>. -Example: +Most of the C<Apache::> modules on CPAN are dealing with this +phase. In fact most of the developers spend the majority of their time +working on handlers that generate response content. + +Let's write a simple response handler, that just generates some +content. This time let's do something more interesting than printing +I<Hello world". Let's write a handler that prints itself: + + file:MyApache/Deparse.pm + ------------------------ + package MyApache::Deparse; + + use Apache::RequestRec (); + use Apache::RequestIO (); + use B::Deparse (); + + use Apache::Const -compile => 'OK'; + + sub handler { + my $r = shift; + + $r->content_type('text/plain'); + $r->print('sub handler ', B::Deparse->new->coderef2text(\&handler)); + + return Apache::OK; + } + 1; + +To enable this handler add to I<httpd.conf>: + + <Location /deparse> + SetHandler modperl + PerlResponseHandler MyApache::Deparse + </Location> + +Now when the server is restarted and we issue a request to +I<http://localhost/deparse> we get the following response: + + sub handler { + package MyApache::Deparse; + my $r = shift @_; + $r->content_type('text/plain'); + $r->print('sub handler ', 'B::Deparse'->new->coderef2text(\&handler)); + return 0; + } + +if you compare it to the source code, it's pretty much the +same. C<B::Deparse> is fun to play with!
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]