Apache2-Controller
view release on metacpan or search on metacpan
lib/Apache2/Controller.pm view on Meta::CPAN
correct decisions to rely on open-source software.
You deploy the same Apache, the
same CPAN modules and your whole application package to every server,
and attach a url-generating subroutine to the L<Template|Template> stash
that puts in a different hostname when the URI is one of your
load-intensive functions.
<a href="[% myurl('/easy') %]">easy</a> "http://pony.x.y/easy"
<a href="[% myurl('/hard') %]">hard</a> "http://packhorse.x.y/hard"
Web designers can be taught to use this function C<< myurl() >>,
but system admins
maintain the map that it loads to figure out what servers to use.
Then the Apache2 config files on those
packhorse servers would pre-load only the subclassed controllers
that you needed, and redirect all other uri requests to the pony servers.
=cut
use strict;
use warnings FATAL => 'all';
use English '-no_match_vars';
use base qw( Apache2::Controller::Methods );
use Readonly;
use Scalar::Util qw( blessed );
use Log::Log4perl qw(:easy);
use YAML::Syck;
use Digest::SHA qw( sha224_base64 );
use URI;
use HTTP::Status qw( status_message );
use Scalar::Util qw( looks_like_number );
use Apache2::Controller::X;
use Apache2::Controller::Funk qw( log_bad_request_reason );
use Apache2::Request;
use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::RequestUtil ();
use Apache2::Log;
use Apache2::Const -compile => qw( :common :http );
=head1 FUNCTIONS
=head2 a2c_new
$handler = MyApp::C::ControllerSubclass->a2c_new( Apache2::RequestRec object )
This is called by handler() to create the Apache2::Controller object
via the module chosen by your L<Apache2::Controller::Dispatch> subclass.
We use C<< a2c_new >> instead of the conventional C<< new >>
because, in case you want to suck in the L<Apache2::Request>
methods with that module's automagic, then you don't get
confused about how C<<SUPER::>> behaves. Otherwise you
get into a mess of keeping track of the order of bases
so you don't call C<< Apache2::Request->new() >> by accident,
which breaks everything.
=head3 subclassing C<a2c_new()>
To set params for the L<Apache2::Request> object,
you have to subclass C<a2c_new()>.
package MyApp::ControllerBase;
use base qw( Apache2::Controller Apache2::Request );
sub a2c_new {
my ($class, $r) = @_;
return SUPER::new(
$class, $r,
POST_MAX => 65_535,
TEMP_DIR => '/dev/shm',
);
# $self is already blessed in the class hierarchy
}
package MyApp::Controller::SomeURI;
use base qw( MyApp::ControllerBase );
sub allowed_methods qw( uri_one uri_two );
sub uri_one { # ...
If you need to do the same stuff every time a request
starts, you can override the constructor through a
class hierarchy.
package MyApp::ControllerBase;
use base qw( Apache2::Controller Apache2::Request );
sub new {
my ($class, $r, @apr_override_args) = @_;
my $self = SUPER::new(
$class, $r,
POST_MAX => 65_535,
TEMP_DIR => '/dev/shm',
@apr_override_args,
);
# $self is already blessed in the class hierarchy
# do request-startup stuff common to all controller modules
return $self;
}
package MyApp::Controller::SomeURI;
use base qw( MyApp::ControllerBase );
sub allowed_methods qw( uri_one uri_two );
sub new {
my ($class, $r) = @_;
my $self = SUPER::a2c_new(
$class, $r,
);
# no need to bless, A2C blesses into the child class
# do request-startup stuff for this specific controller
return $self;
}
sub uri_one {
my ($self) = @_;
$self->content_type('image/gif');
# ...
return Apache2::Const::HTTP_OK;
}
sub uri_two { # ...
Similarly, to do something always at the end of every
request, from within the dispatched PerlResponseHandler:
package MyApp::Controller::SomeURI;
use Devel::Size;
use Log::Log4perl qw(:easy);
my $MAX = 40 * 1024 * 1024;
sub DESTROY {
my ($self) = @_;
my $size = total_size($self); # whoo baby!
INFO("size of $self->{class} is bigger than $MAX!") if $size > $MAX;
return; # self is destroyed
}
See L<USING INHERITANCE> below for more tips.
=cut
my %temp_dirs = ( );
my %post_maxes = ( );
sub a2c_new {
my ($class, $r, @apr_opts) = @_;
DEBUG sub {
"new $class, reqrec is '$r', apr_opts:\n".Dump(\@apr_opts)
};
my $self = {
class => $class,
};
bless $self, $class;
DEBUG "creating Apache2::Request object";
my $req = Apache2::Request->new( $r, @apr_opts );
DEBUG "request object is '$req'";
$self->{r} = $req; # for Apache2::Request subclass automagic
my $pnotes_a2c = $req->pnotes->{a2c} || { };
( run in 1.426 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )