Apache::Request::Dispatcher - dispatches requests to a sub-class of Apache::Request::Controller
SYNOPSIS
<Location /myApplication>
SetHandler perl-script
Perlhander Apache::Request::Dispatcher
SetEnv DispatcherConf /path/to/file.cfg
setEnv APP_NAME myApplication
</Location>
DESCRIPTION
Apache::Request::Dispatcher is a mod_perl handler which handles Apache HTTP requests under mod_perl, and dispatches them to a sub-class of Apache::Request::Controller (after some initial request setup has been performed).
If required, it will establish a connection to a database using the DBI, retrieve (or create) session data for this request (using Apache::Session), initialise a template processor (using the Template-Toolkit).
The Dispatcher parses the URI of the request to determine which subclass of Apache::Request::Controller to then pass control to.
Parsing of the URI occurs as follows:
APP_NAME (environment set in Apache Config) is removed from the begining of the URI, so that:
'/myApplication/SubClass/action'
becomes: 'SubClass/action'
or
'/myApplication/Sub/Class/action'
becomes: 'Sub/Class/action'
This is then converted to a module name, and a method name, such as:
Apache::Request::Controller::SubClass or
Apache::Request::Controller::Sub::Class
with action() being the method name.
It should be noted that if the SubClass or Action name contain any thing other than [A-Za-z0-9_] then the request is declined.
The dispatcher then dynamically inherits from the module name, and then calls $self->action().
The action() method of the controller is then called in an object-oriented fashion, with a dispatcher object passed in as its first parameter.
This object contains the following hash elements:
request => $r, # The Apache Request Object
dbh => $dbh, # The Database Connection Object
cfg => $cfg, # The AppConfig object
template => $template, # The Template Processor
apr => $q, # The CGI/libapreq object
session => \%session # Any session data for this user
Depending on the configuration file, 'dbh' or 'session' may be undefined if they've been turned off.
an example controller method might be written as follows:
package Apache::Request::Controller::SubClass;
our @ISA = qw(Apache::Request::Controller);
use strict;
use Apache::Const qw(:common :methods :http);
sub action
{
my $self = shift;
my $thing = getThingByID($self->{'dbh'}, $self->{'apr'}->param('thingId'));
$self->{'request'}->status(HTTP_OK);
$self->{'request'}->content_type('text/html');
$self->{'template'}->process('myTemplate', {thing => $thing});
return OK;
}
1;
Special Actions
- __cache()
-
Generally, the controllers that are dispatched to will generate dynamic content, and as such the dispatcher automatically sets the browsers caching policy to not cache any content. However, if your Controller sub-class has a method called __cache() then will be used to define the caching policy. The action name is given as a parameter to the __cache() method, and based on this, the __cache() method should return 1 to allow caching, or zero to prevent it.
For exmaple, if your Controller sub-class provides 2 actions, staticContent() and dynamicContent(), then your __cache() method can control the caching policy as follows:
sub __cache { my $action = shift; my $policy = { staticContent => 1, dynamicContent => 0}; return $policy->{$action} || 0; # Default to no caching. }
If your Controller sub-class wants to turn off caching globally, then you can just return zero regardless of what the action name is.
- __index()
-
If the dispatcher cannot work out which action the request is for (this happens on a URI such as '/myApplication/SubClass') then the dispatcher checkes to see if the Controller SubClass has a 'default' action by calling __index(). If this method does not exist, then the request is declined. The __index() method should return the name of the default action, such as:
sub __index { return 'listAllItems'; }
Template Defaults
The template processor has the following defaults defined, and may be used by all templates:
- DisplayNumber()
-
This template variable is a reference to a subroutine which will add comma's in the right place in numbers, for exmaple:
[% DisplayNumber(1000) %] becomes 1,000
- DisplayDate()
-
This template variable is a reference to a subroutine which will take a time value (in the form of seconds since the epoch) and display the actual date. You may optionally specify an strftime() format:
[% DisplayDate( CURRENT_TIME, '%a %d %B %Y' ) %]
- DisplayTime()
-
This template variable is a reference to a subroutine which will take a time value (in the form of seconds since the epoch) and displays the time-of-day. You may optionally specify an strftime() format:
[% DisplayTime( CURRENT_TIME, '%a %d %B %Y' ) %]
- DisplayDateTime()
-
This template variable is a reference to a subroutine which will take a time value (in the form of seconds since the epoch) and displays the date and time of day
[% DisplayDateTime( CURRENT_TIME ) %]
- DisplayDuration()
-
This template variable is a reference to a subroutine which will take a number of seconds as input, and output a string of the form 'H hours, M minutes and S seconds', eg:
Last Modified: [% DisplayDuration( CURRENT_TIME - LAST_MODIFIED %]
- APP_NAME
-
This template variable is a string which represents the application name, as defined by the environment variable APP_NAME.
- REQUEST
-
This template variable is an Apache2::RequestRec object, so that the template can have access to the current URI etc. Its not really meant to be used to set any outgoing headers or any thing tho, as setting up the response should really be done in the Controller.
The Configuration File
The dispatcher can be used to dispatch to multiple controllers that dont even need to belong to the same application, and each can application can have its own database connection and set of templates. This is achieved by having Apache specify which configuration file to use based on the Location of the request URI. For example:
<Location /myApplication>
SetHandler perl-script
Perlhander Apache::Request::Dispatcher
SetEnv DispatcherConf /path/to/file.cfg
setEnv APP_NAME myApplication
</Location>
will specify that all requests with a root-URI of /myApplication will use the configuration file as specified in the DispatcherConf environment variable, which is /path/to/file.cfg in the above example.
The contents of this configuration file are as follows:
db_dsn="DBI:Pg:database=myApplication;host=127.0.0.1"
db_username=apache
db_password=apache
templatePath="/data/myApplication/templates"
defaultController=WelcomePage
# If you wish to use sessions, uncomment this and make sure you have
# created the sessions table within the database db_dsn.
useSessions="Apache::Session::Postgres"
sessionTable="sessions"
where db_dsn, db_username, and db_password specifies the database connection options, templatePath specifies where the templates are all stored, and defaultController specifies which controller is the default, so that if a request for '/myApplication' is recieved, it will be converted to '/myApplication/WelcomePage', which will in turn get converted to Apache::Request::Controller::WelcomePage.
At a minimum, you have to have templatePath defined. If you dont specify a default Controller, then the top-level URI will not work.
AUTHOR
Bradley Kite <bradley-cpan@kitefamily.co.uk>
If you wish to email me, then please remove the '-cpan' part of my email address as anything addressed to 'bradley-cpan' is assumed to be spam and is not read.
SEE ALSO
Apache::Request::Controller, DB::Table, DB::Table::Row, DBI, perl
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 23:
=pod directives shouldn't be over one line long! Ignoring all 2 lines of content