NAME
Apache::Dispatch - call PerlHandlers with the ease of Registry scripts
SYNOPSIS
httpd.conf:
PerlModule Apache::Dispatch
PerlModule Bar
DispatchExtras Pre Post Error
DispatchStat On
DispatchISA "My::Utils"
DispatchAUTOLOAD Off
<Location /Foo>
SetHandler perl-script
PerlHandler Apache::Dispatch
DispatchPrefix Bar
DispatchFilter Off
</Location>
DESCRIPTION
Apache::Dispatch translates $r->uri into a class and method and runs it as a PerlHandler. Basically, this allows you to call PerlHandlers as you would Regsitry scripts without having to load your httpd.conf with a slurry of <Location> tags.
EXAMPLE
in httpd.conf
PerlModule Apache::Dispatch
PerlModule Bar
<Location /Foo>
SetHandler perl-script
PerlHandler Apache::Dispatch
DispatchPrefix Bar
</Location>
in browser:
http://localhost/Foo/baz
the results are the same as if your httpd.conf looked like:
<Location /Foo>
SetHandler perl-script
PerlHandler Bar->dispatch_baz
</Location>
but with the additional security of protecting the class name from the browser and keeping the method name from being called directly. Because any class under the Bar:: hierarchy can be called, one <Location> directive is able to handle all the methods of Bar, Bar::Baz, etc...
CONFIGURATION DIRECTIVES
DispatchPrefix
The base class to be substituted for the $r->location part of the
uri. Applies on a per-location basis only.
DispatchExtras
An optional list of extra processing to enable per-request. They
may be applied on a per-server or per-location basis, and must be
turned on explicitly. If the main handler is not a valid method
call, the request is declined prior to the execution of any of the
extra methods.
Pre - eval()s Foo->pre_dispatch($r) prior to dispatching the
uri. The $@ of the eval is not checked in any way.
Post - eval()s Foo->post_dispatch($r) prior to dispatching the
uri. The $@ of the eval is not checked in any way.
Error - If the main handler returns other than OK then
Foo->error_dispatch($r, $@) is called and return status
of it is returned instead. Unlike the pre and post
processing routines above, error_dispatch is not wrapped
in an eval, so if it dies, the Apache::Dispatch dies,
and Apache will process the error using ErrorDocument,
custom_response(), etc.
With error_dispatch() disabled, the return status of the
the main handler is returned to the client.
DispatchStat
An optional directive that enables reloading of the module that is
the result of the uri to class->method translation, similar to
Apache::Registry, Apache::Reload, or Apache::StatINC. It applies
on a per-server or per-location basis.
On - Test the called package for modification and reload on
change
Off - Do not test or reload the package (Default)
ISA - Test the called package, and all other packages in the
called package's @ISA, and reload on change
DispatchAUTOLOAD
An optional directive that enables unknown methods to use
AutoLoader. It may be applied on a per-server or per-location
basis and defaults to Off. Please see the special section on
AUTOLOAD below.
On - Allow for methods to be defined in AUTOLOAD method
Off - Turn off search for AUTOLOAD method (Default)
DispatchISA
An optional list of parent classes you want your dispatched class
to inherit from. It may be applied on a per-server or per-location
basis.
DispatchFilter
If you have Apache::Filter 1.013 or above installed, you can take
advantage of other Apache::Filter aware modules. Please see the
section on FILTERING below. DispatchFilter may be applied on a
per-location basis. In keeping with Apache::Filter standards,
PerlSetVar Filter has the same effect as DispatchFilter but with
lower precedence.
On - make the output of your module Apache::Filter aware
Off - do not use Apache::Filter (Default)
SPECIAL CODING GUIDELINES
Migrating to Apache::Dispatch is relatively painless - it requires only a few minor code changes. The good news is that once you adapt code to work with Dispatch, it can be used as a conventional mod_perl method handler, requiring only a few considerations. Below are a few things that require attention.
In the interests of security, all handler methods must be prefixed with 'dispatch_', which is added to the uri behind the scenes. Unlike ordinary mod_perl handlers, for Apache::Dispatch there is no default method (with a tiny exception - see NOTES below).
Apache::Dispatch uses object oriented calls behind the scenes. This means that you either need to account for your handler to be called as a method handler, such as
sub dispatch_bar {
my $self = shift; # your class
my $r = shift;
}
or get the Apache request object directly via
sub dispatch_bar {
my $r = Apache->request;
}
If you want to use the handler unmodified outside of Apache::Dispatch, you must do two things:
prototype your handler:
sub dispatch_baz ($$) {
my $self = shift;
my $r = shift;
}
change your httpd.conf entry:
<Location /Foo>
SetHandler perl-script
PerlHandler Bar->dispatch_baz
</Location>
That's it - now the handler can be swapped in and out of Dispatch without further modification. All that remains to be done is proper configuration of httpd.conf.
FILTERING
Apache::Dispatch provides for output filtering using Apache::Filter 1.013 and above.
<Location /Foo>
SetHandler perl-script
PerlHandler Apache::Dispatch Apache::Compress
DispatchPrefix Bar
DispatchFilter On
</Location>
Your handler need do nothing special to make its output the start of the chain - Apache::Dispatch registers itself with Apache::Filter and hides the task from your handler. Thus, any dispatched handler is automatically Apache::Filter ready without the need for additional code.
The only caveat is that you must use the request object that is passed to the handler and not get it directly using Apache->request.
AUTOLOAD
Support for AUTOLOAD has been made optional, but requires special care. Please take the time to read the camel book on using AUTOLOAD with can() and subroutine declarations (3rd ed pp326-329).
Basically, you declare the methods you want AUTOLOAD to capture by name at the top of your script. This is necessary because can() will return true if your class (or any parent class) contains an AUTOLOAD method, but $AUTOLOAD will only be populated for declared method calls. Hence, without a declaration you won't be able to get at the name of the method you want to AUTOLOAD.
DispatchISA introduced some convenience, but some headaches as well - if you inherit from a class that uses AutoLoader then ALL method calls are true. And as just explained, AUTOLOAD() will not know what the called method was. This may represent a problem if you aren't aware that, say, CGI.pm uses AutoLoader and spend a few hours trying to figure out why all of a sudden every URL under Dispatch is bombing.
If you decide to use DispatchISA it is HIGHLY SUGGESTED that you do so with DispatchAUTOLOAD Off (which is the default behavior).
NOTES
If you define a dispatch_index() method calls to /Foo will default to it. Unfortunately, this implicit translation only happens at the highest level - calls to /Foo/Bar will translate to Foo->Bar() (that is, unless Foo::Bar is your DispatchPrefix, in which case it will work but /Foo/Bar/Baz will not, etc). Explicit calls to /Foo/index follow the normal dispatch rules.
There is no require()ing or use()ing of the packages or methods prior to their use as a PerlHandler. This means that if you try to dispatch a method without a PerlModule directive or use() entry in your startup.pl you probably will not meet with much success. This adds a bit of security and reminds us we should be pre-loading that code in the parent process anyway...
If the uri can be dispatched but contains anything other than [a-zA-Z0-9_/-] Apache::Dispatch declines to handle the request.
Like everything in perl, the package names are case sensitive.
Warnings have been left on, so if you set an invalid class with DispatchISA you will see a message like: Can't locate package Foo::Bar for @Bar::Baz::ISA at .../Apache/Dispatch.pm line 277.
Verbose debugging is enabled by setting $Apache::Dispatch::DEBUG=1. Very verbose debugging is enabled at 2. To turn off all debug information set your Apache LogLevel directive above info level.
This is alpha software, and as such has not been tested on multiple platforms or environments for security, stability or other concerns. It requires PERL_DIRECTIVE_HANDLERS=1, PERL_LOG_API=1, PERL_HANDLER=1, and maybe other hooks to function properly.
FEATURES/BUGS
If a module fails reload under DispatchStat, Apache::Dispatch declines the request. This might change to SERVER_ERROR in the future...
SEE ALSO
perl(1), mod_perl(1), Apache(3), Apache::Filter(3), Apache::Reload(3), Apache::StatINC(3)
AUTHOR
Geoffrey Young <geoff@cpan.org>
COPYRIGHT
Copyright 2000 Geoffrey Young - all rights reserved.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.