Apache2-Controller
view release on metacpan or search on metacpan
lib/Apache2/Controller/Dispatch.pm view on Meta::CPAN
bar: MyApp::Controller::Bar
'foo/bar': MyApp::Controller::Foo::Bar
biz: MyApp::C::Biz
'biz/baz': MyApp::Controller::Biz::Baz
# lib/MyApp/Dispatch.pm:
package MyApp::Dispatch;
use base qw( Apache2::Controller::Dispatch::Simple );
1;
=head2 HARD WAY
# vhost.conf:
PerlModule MyApp::Dispatch
<Location />
SetHandler modperl
PerlInitHandler MyApp::Dispatch
</Location>
# lib/MyApp/Dispatch.pm:
package MyApp::Dispatch;
use strict;
use warnings FATAL => 'all';
use base qw( Apache2::Controller::Dispatch::Simple );
# return a hash reference from dispatch_map()
sub dispatch_map { return {
foo => 'MyApp::C::Foo',
bar => 'MyApp::C::Bar',
'foo/bar' => 'MyApp::C::Foo::Bar',
biz => 'MyApp::C::Biz',
'biz/baz' => 'MyApp::C::Biz::Baz',
} }
# or use directive A2C_Dispatch_Map to refer to a YAML file.
1;
=head1 DESCRIPTION
C<Apache2::Controller::Dispatch> forms the base for the
PerlInitHandler module to dispatch incoming requests to
libraries based on their URL.
You don't use this module. You use one of its subclasses
as a base for your dispatch module.
=head1 WHY A MAP?
Natively, this does not try to figure out the appropriate
module using any complex magic. Instead, you spell out the
uris under the handler location and what controller
modules you want to handle paths under that URL, using a
directive. (L<Apache2::Controller::Directives/A2C_Dispatch_Map>)
The trouble with automatic controller module detectors is
that parsing the URI and doing C<< eval "use lib $blah" >>
up through the URI path is that is computationally expensive.
Maintaining a URI map file is not that difficult and also is
convenient because you can move libraries around, point different
URI's to the same controller library, etc. For example to bring
part of your site off-line and see 'under construction', create
a controller to print the right message, change all the uri's
in the map and bump the server.
(Can I trap a signal so it
clears and reloads map files if Apache2 is HUP'd? That would be cool.
Or a timeout that would cause children to reload the file.)
Different dispatch types use different structure in the
map, but it is conceptually the same. The structure is
loaded into memory and then the uri can be parsed very
quickly to locate the correct controller.
=head1 SUBCLASSES
Subclasses of this module implement C<< find_controller() >>
in different ways, usually interpreting the URI from a
hash reference returned by C<< dispatch_map() >> in your subclass.
Or, if you provide the directive C<< A2C_Dispatch_Map >> to specify
a map file, this module will load it with L<YAML::Syck/LoadFile>.
See L<Apache2::Controller::Dispatch::Simple> and
L<Apache2::Controller::Dispatch::HashTree> for other
dispatch possibilities.
Any implementation of find_controller() should throw an
L<Apache2::Controller::X> with status C<< Apache2::Const::NOT_FOUND >>
in the
event that the detected method selected does not appear in the list of
C<< allowed_methods() >> in the controller module. ex:
a2cx status => Apache2::Const::NOT_FOUND;
See L<Apache2::Controller::Funk/check_allowed_method>. This is
internal stuff mostly, you don't have to implement your own
type of dispatch mechanism unless you are a nut like me.
Successful run of find_controller() should result in four items of
data being set in request->pnotes->{a2c}:
=over 4
=item pnotes->{a2c}{relative_uri} = matching part of uri relative to location
This is the uri relative to the location. For example,
if the dispatch module is the init handler in a C<< <Location /subdir> >>
config block, then for /subdir/foo/bar/biz/zip in this example code,
relative_uri should be 'foo/bar' because this is the key of %dispatch_map
that was matched. /subdir/foo/bar is the 'virtual directory.'
If there is no relative uri, for example if the uri requested was /subdir
and this is the same as the location, then
C< pnotes->{a2c}{relative_uri} > would be set to
the empty string.
( run in 0.727 second using v1.01-cache-2.11-cpan-e1769b4cff6 )