Apache2-Controller

 view release on metacpan or  search on metacpan

lib/Apache2/Controller.pm  view on Meta::CPAN


The controller handler returns your set HTTP status code
or OK (0) to Apache.  In general you return the status code
that you want to set, or return OK.  Or you can set it with
C<< $r->status() >> and return OK.  
You can't return DONE or DECLINED. (If you find you need
to do that for some reason please contact me.)

See L<Apache2::Const/:http>
and L<Apache2::Controller::Refcard>.  You can also set
C<< status_line() >> or throw L<Apache2::Controller::X>
exceptions to be processed by an error template,
if you're using some form of template rendering - see
the section on errors below.

Add handlers in your config file with your own modules which 
C<use base> to inherit from these classes as you need them:

=head2 PerlHeaderParserHandler Apache2::Controller::Session

C<< $r->pnotes->{a2c}{session} >> automatically loaded from and 

lib/Apache2/Controller.pm  view on Meta::CPAN

access those methods via C<< $self->{r} >>.

=head1 RETURN VALUES

Your controller methods should use C<< eval { } >> if necessary and
act accordingly, set the right things for C<Apache2::RequestRec> 
and return the right HTTP constant.  See L<Apache2::Const/:http>
and L<Apache2::Controller::Refcard>.

In the event of an error, if you wish, use L<Apache2::Controller::X>
and throw one with field 'status' set to a valid HTTP return code.  
This lets you implement nice error templates if your controller uses 
L<Apache2::Controller::Render::Template> as a base.
See L<ERRORS> below.

Success in the controller method normally should just return the
appropriate HTTP status code.  You can return HTTP_OK (200) if that
is what you mean, or it is the default status if you return OK (0).

Or, if you do C<< $self->status( Apache2::Const::HTTP_SOMETHING ) >>
and then just C<< return() >>

lib/Apache2/Controller.pm  view on Meta::CPAN

to the error log at the WARN level of L<Log::Log4perl> from
this module's namespace.  If errors crop up from
other A2C request phase handlers, try setting
WARN log level for L<Apache2::Controller::NonResponseBase>
or L<Apache2::Controller::NonResponseRequest>.

Also see L<Apache2::Controller::Render::Template>.

You can use or subclass L<Apache2::Controller::X>,
to use C<< a2cx() >>,
or you can throw your own exception objects,
or just C<< die() >>, or C<< croak() >>,
or set C<< $self->status >>, headers etc., possibly printing content, 
or return the appropriate status from your controller method.

See L<Apache2::Controller::X> for help on throwing exceptions
with HTTP status, data dumps, etc.

If your code does break, die or throw an exception, this is 
caught by Apache2::Controller.  If your controller module implements
an C<<error() >> method, 
then C<< $handler->error() >> will be called passing the C<< $EVAL_ERROR >>
or exception object as the first argument.

 package MyApp::C::Foo;
 use YAML::Syck;
 # ...
 sub error {
     my ($self, $X) = @_;

lib/Apache2/Controller.pm  view on Meta::CPAN

                if (exists $supports_error_method{$class}) {
                    $error_method_status = $handler->error($X);
                } 
                elsif ($class->can('error')) {
                    $supports_error_method{$class} = 1;
                    $error_method_status = $handler->error($X); 
                }
                $used_error_method_successfully = 1;
            };

            # trap unknown errors that might have been thrown
            # by the error() subroutine
            $X = Exception::Class->caught('Apache2::Controller::X')
                || $EVAL_ERROR 
                || $X;
        }

        my $x_status = $ref && $blessed && $X->can('status')
            ? $X->status : undef;

        $status 

lib/Apache2/Controller/Auth/OpenID.pm  view on Meta::CPAN

use Net::OpenID::Consumer;
use URI;
use List::MoreUtils qw(any);

use Apache2::Const -compile => qw( OK SERVER_ERROR REDIRECT );

use Apache2::Controller::X;

=head2 new

Overloaded constructor will always throw an L<Apache2::Controller::X>
because this module does not work.

=cut

sub new {
    a2cx __PACKAGE__." is disabled, does not work, do not use.";
}

# hopefully we get the same default consumer secret as in top level
use Apache2::Controller::Const qw( $DEFAULT_CONSUMER_SECRET );

lib/Apache2/Controller/DBI/Connector.pm  view on Meta::CPAN

=head1 METHODS

=head2 process

Gets DBI connect arguments by calling C<< $self->dbi_connect_args() >>,
then connects C<< $dbh >> and stashes it in C<< $r->pnotes->{a2c}{dbh} >>
or the name you select.

The $dbh has a reference in package space, so controllers using it
should always call commit or rollback.  It's good practice to use
C<< eval >> anyway and throw an L<Apache2::Controller::X> or
your subclass of it (using C<< a2cx() >>,
so you can see the function path trace in the logs when the error occurs.

The package-space $dbh for the child persists across requests, so
it is never destroyed.  However, it is assigned with C<< DBI->connect() >>
on every request, so that L<Apache::DBI> will cache the database handle and
actually connect it only if it cannot be pinged.

=cut

lib/Apache2/Controller/Dispatch.pm  view on Meta::CPAN

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.

lib/Apache2/Controller/Dispatch.pm  view on Meta::CPAN

    $self->find_controller();
    my $controller = $self->{controller} = $pnotes->{a2c}{controller};
    DEBUG "found controller '$controller'";

    # save the dispatch class name in notes in case we have to
    # re-dispatch somewhere along the line if the uri changes
    # (this is done by Apache2::Controller::Auth::OpenID, for instance)
    $pnotes->{a2c}{dispatch_class} = $class;

    # set the handler for that class 
    # - this has to be the last thing it does in case an exception is thrown

    DEBUG "setting PerlResponseHandler '$controller'";
    $r->set_handlers(PerlResponseHandler => [ "$controller" ]); 
    # "" == lame but true, must stringify lib name because
    # the value is some kind of blessed scalar reference or something

    DEBUG sub { "Done with process() for uri ".$r->uri };
    
    return Apache2::Const::OK;
}

lib/Apache2/Controller/Funk.pm  view on Meta::CPAN


=cut

use version;
our $VERSION = version->new('1.001.001');

=head1 SYNOPSIS

 $bool = controller_allows_method($class, $method); 

 check_allowed_method($class, $method);     # throws NOT_FOUND exception

=head1 DESCRPTION

Useful routines for both Apache2::Controller and Apache2::Controller::Dispatch
objects to run.  Results and whether to 'require' are cached in this package's
namespace across requests, optimizing efficiency per mod_perl2 child, and are
queried futher using 'exists', which is very fast.

=cut

lib/Apache2/Controller/Log/SessionSave.pm  view on Meta::CPAN

use Apache2::Controller::X;
use Apache2::Controller::Const qw( $DEFAULT_SESSION_SECRET );

=head2 process

If aborted connection, don't save, and return. 

If status >- 300 and not set C<< $r->pnotes->{a2c}{session_force_save} >>,
don't save, and return.

If session object is not tied, throw an error.  This may not do
anything noticible to the user since the request response is
finished, but you'll see it in the log.

Update the top-level timestamp in the session if the directive
C<A2C_Session_Always_Save> is set.

Untie the session so Apache::Session saves it or not.

=cut

lib/Apache2/Controller/Methods.pm  view on Meta::CPAN

of C<Apache2::Cookie>, and input headers could possibly change
via filters, and it would create a circular reference to C<< $r >>
if you stuck it in pnotes.  It always creates a new Jar object,
which acts as a utility object to parse the source information
that remains in C<< $r >>, if I understand this correctly.

If the directive << A2C_Skip_Bogus_Cookies >> is set, fetches
jar in eval and returns C<< $EVAL_ERROR->jar >> if the error
is an L<APR::Request::Error> and the code is C<< APR::Request::Error::NOTOKEN >>,
indicating a cookie with a value like '1' sent by a defective client.
Any other L<APR::Error> will be re-thrown as per that doc, 
otherwise A2C will throw an L<Apache2::Controller::X> with the error.
(See L<http://comments.gmane.org/gmane.comp.apache.apreq/4477> - 
closes RT #61744, thanks Arkadius Litwinczuk.)  Skipping these
errors is optional since they might be important for debugging 
clients that send invalid headers.

See L<Apache2::Cookie>, L<Apache2::Controller::Directives>.

=cut

sub get_cookie_jar {

lib/Apache2/Controller/Methods.pm  view on Meta::CPAN

}

sub _get_cookie_jar_normal {
    my ($self) = @_;
    my $r = $self->{r};
    my $jar;
    eval { $jar = Apache2::Cookie::Jar->new($r) };
    if (my $err = $EVAL_ERROR) {
        my $ref = ref $err;
        DEBUG "error creating cookie jar (reftype '$ref'): '$err'";
        die $err if $ref; # rethrow blessed APR::Error errors
        a2cx "unknown error creating cookie jar: '$err'";
    }
    DEBUG sub {
        my $cookie = $r->headers_in->{Cookie};
        $cookie = $cookie ? qq{$cookie} : '[no raw cookie string]';
        eval { my @cookies = $jar->cookies() };
        a2cx "error getting cookie from jar that worked: '$EVAL_ERROR'"
            if $EVAL_ERROR;
        return 
            "raw cookie header: $cookie\n"

lib/Apache2/Controller/Methods.pm  view on Meta::CPAN

                my $errstr = APR::Error::strerror($code);
                DEBUG sub { 
                    my $ip = $r->connection->remote_ip 
                        || '[ could not detect remote ip?? ]';
                    return "bad cookies from ip $ip, skipping error: '$err'"
                        ." ($code/$errstr)";
                };
                $jar = $err->jar;
            }
            else {
                DEBUG "rethrowing other APR::Error: '$err'";
                die $err;
            }
        }
        else {
            a2cx "unknown error (reftype '$ref') getting cookie jar: '$err'";
        }
    }
    DEBUG sub {
        my $cookie = $r->headers_in->{Cookie};
        $cookie = $cookie ? qq{$cookie} : '[no raw cookie string]';

lib/Apache2/Controller/Refcard.pm  view on Meta::CPAN


=head2 status

If you're like me, you get confused as to which status codes are http
status codes and which ones are used internally by Apache2 to signal the
&handler subroutine exit status and return or deny further control to 
the server.

$r->status is set with the right value, usually HTTP_OK or 
HTTP_(which might be overridden by an error in case an
exception is thrown somewhere with ), and then handler() returns 
Apache2::Const::OK in any case.  So far.  This might change if
someone gets me wise to what's actually going on.

  RC                Apache2::Const::*  HTTP::Status::status_message($RC)
 -----------------------------------------------------------------------
 -02                               DONE                             -
 -01                           DECLINED                             -
 000                                 OK                             -
 100                      HTTP_CONTINUE                      Continue
 101           HTTP_SWITCHING_PROTOCOLS           Switching Protocols

lib/Apache2/Controller/Render/Template.pm  view on Meta::CPAN

    my $tt = $self->get_tt_obj();
    # pass Apache2::Request object to print directly.
    $tt->process($template, $self->{stash}, $self->{r}) || a2cx $tt->error();

    return;
}

=head2 error

If your template directory contains a subdirectory named 'error', 
then when the controller throws an exception, the exception object will
be passed to a selected error template as 'X' in the stash.  It also
sets status (number) and status_line 
(from HTTP::Status::status_message() or from the values 
set in the L<Apache2::Controller::X> exception).

If you have a template $template_dir/error/$status.html, 
where $status is the numeric http status code,
then it will use that template.

For example:

lib/Apache2/Controller/Render/Template.pm  view on Meta::CPAN

    my $template_dir = $self->get_directive('A2C_Render_Template_Path')
        || a2cx 'A2C_Render_Template_Path not defined.';

    DEBUG sub { "A2C_Render_Template_Path:\n".Dump($template_dir) };

    if (exists $error_templates{$template_dir}{$status_file}) {

        my $template = $error_templates{$template_dir}{$status_file};
        
        # if exists but undefined, it means it failed totally.
        # forget about using an error template and just rethrow the error
        if (!defined $template) {
            if (ref($X) && $X->isa('Apache2::Controller::X')) {
                $X->rethrow();
            }
            else {
                a2cx "Cannot process any template for unknown-type error: $X";
            }
        }

        $self->{template} = $template;
        $self->render();
    }
    else {

lib/Apache2/Controller/Render/Template.pm  view on Meta::CPAN

        my %try_errors = ( );
        $self->{template} = "errors/$status_file.html";
        eval { $self->render() };

        # if got an error using that file name, try the default error file:
        if ($EVAL_ERROR) {
            $try_errors{$self->{template}} = "$EVAL_ERROR";
            $self->{template} = "errors/default.html";
            eval { $self->render() };

            # and if error template doesn't work, throw back original error
            if ($EVAL_ERROR) {
                DEBUG "Error rendering error file: $EVAL_ERROR";
                $try_errors{$self->{template}} = "$EVAL_ERROR";
                $error_templates{$template_dir}{$status_file} = undef;
                if (ref $X && $X->isa('Apache2::Controller::X')) {
                    $X->rethrow();
                }
                else {
                    my $dump = { tries => \%try_errors, reftype => ref $X };
                    a2cx message    => "$X",
                        status      => $status,
                        status_line => $status_line,
                        'dump'      => $dump;
                }
            }
        }

lib/Apache2/Controller/Session.pm  view on Meta::CPAN

to save stuff, and then if something goes wrong, it is as if this
rolls back.

A C<PerlLogHandler> subroutine is 'unshifted' to the request stack
which decides whether to save changes to the session.  By default,
it saves changes only if A) the connection is not aborted,
and B) your controller set HTTP status < 300,
i.e. it returned C<OK> (0), one of the C<HTTP_CONTINUE> family (100+)
or one of the C<HTTP_OK> family (200+).  

So for an C<HTTP_SERVER_ERROR>, or throwing an exception, redirecting,
forbidding access, etc (>= 300), it normally would not save changes.
If your L<Apache2::Controller> controller module returns one of these 
non-OK statuses, but you want to force the saving of the session contents, 
set C<< $self->pnotes->{a2c}{session_force_save} = 1 >> before
your response phase controller returns a status to L<Apache2::Controller>.

If the connection is aborted mid-way (i.e. the pipe was broken
due to a network failure or the user clicked 'stop'
in the browser), then the session will not be saved,
whether you set the force save flag or not.

lib/Apache2/Controller/Session.pm  view on Meta::CPAN

query params, and C<set_session_id()> would push a C<PerlOutputFilterHandler>
to post-process all other handler output and append the session id param
onto any url links that refer to our site.  That would be cool...
release your own plug-in.
If you wanted to do it with combined cookies and url params in 
this way you could 
overload C<get_session_id()> and C<set_session_id()>, etc. etc.

=head1 ERRORS

C<<Apache2::Controller::Session>> will throw an error exception if the
session setup encounters an error.  

=head1 METHODS

=cut

use strict;
use warnings FATAL => 'all';
use English '-no_match_vars';

lib/Apache2/Controller/X.pm  view on Meta::CPAN

Hierarchy of L<Exception::Class> objects for L<Apache2::Controller>.
All are subclasses of Apache2::Controller::X.

=head1 FIELDS

All Apache2::Controller::X exceptions implement three fields:

=head2 message

Required.
The standard L<Exception::Class> message field.  If you call C<throw()>
or the alias C<a2cx()>
with only one argument, a string, then this gets set as the message
field, which is displayed when the object is referred to in string context.

 eval { a2cx "booyeah" };
 if (my $X = Exception::Class->caught('Apache2::Controller::X')) {
     warn "my exception 'message' was '$X'\n";
     warn $X->trace;
 }

t/unit_exception_object.t  view on Meta::CPAN

use blib;

use English '-no_match_vars';

use Log::Log4perl qw(:easy);

use Test::More qw( no_plan );

use Apache2::Controller::X;

eval { Apache2::Controller::X->throw('horta') };
is("$EVAL_ERROR" => 'horta', 'stringify exception throw works');

eval { Apache2::Controller::X->throw('spock') };
my $X = Exception::Class->caught('Apache2::Controller::X');
ok(defined $X, 'X object is defined after class throw');
SKIP: {
    skip 'X object not defined', 2 unless defined $X;
    isa_ok($X, 'Apache2::Controller::X', 'X isa Apache2::Controller::X');
    can_ok($X, qw( trace message dump status status_line ));
};

eval { a2cx 'mccoy' };
$X = Exception::Class->caught('Apache2::Controller::X');
ok(defined $X, 'X object is defined after alias a2cx');



( run in 0.351 second using v1.01-cache-2.11-cpan-496ff517765 )