AxKit2
view release on metacpan or search on metacpan
lib/AxKit2/Plugin.pm view on Meta::CPAN
foo_bar demo
FOo_bAr demo
which are all equivalent.
This CamelCase declaration:
sub conf_FooBar;
will create this entry:
$self->config('FooBar');
and will have I<exactly> the same config file syntax as the previous example.
By default, multiple values are accepted and stored, while quoting is supported:
FooBar demo1 demo2 "demo 3"
For different ways of parsing/validating configuration directives, you can add
a custom validation routine:
# use predefined "only one argument allowed" validator
sub FooBar : Validate(TAKE1);
# this directive takes a comma separated list of values
sub FooBar : Validate(sub { split(/,/,shift); });
If you want to have custom actions when the directive is parsed, supply a function body:
# store a database connection instead
sub FooBar { my ($self, $value) = @_; return DBI->connect($value); }
# preprocess parameters
sub FooBar { my ($self, @values) = @_; return join(",",@values); }
# return empty list means: don't store anything
sub FooBar { my ($self, @values) = @_; return (); }
Of course, all this can be combined:
# this is a rather nonsensical example, do you spot why?
sub FooBar : Validate(sub { split(/,/,shift); }) {
my ($self, @values) = @_;
return join(",",@values);
}
=head1 AVAILABLE HOOKS
In order to hook into a particular phase of the request you simply write a
method called C<hook_NAME> where C<NAME> is the name of the hook you wish to
connect to.
Example:
sub hook_logging {
If your plugin needs to hook into the same hook more than once, you will need
to write a C<register()> method as shown above. This is usually the case if you
need continuations for some reason (such as doing asynchronous I/O).
All hooks are called as a method on an instance of the plugin object. Params
below are listed without the C<$plugin> or C<$self> object as the first param.
For some plugins returning C<CONTINUATION> is valid. For details on how
continuations work in AxKit2 see L</CONTINUATIONS> below.
In all cases below, returning C<DECLINED> means other plugins/methods for the
same hook get called. Any other return value means execution stops for that
hook.
Following are the available hooks:
=head2 logging
Params: LEVEL, ARGS
Called when something calls C<< $obj->log(...) >> within AxKit. Logger is
expected to provide a way to set log level and ignore logging below the current
level.
Return Values:
=over 4
=item * C<DECLINED> - continue on to further logging plugins
=item * Anything else - stop logging
=back
=head2 connect
Params: None
Called immediately upon connect.
Return Values:
=over 4
=item * C<OK/DECLINED> - connection is OK to go on to be processed
=item * Anything else - connection is rejected
=back
=head2 pre_request
Params: None
Called before headers are received. Useful if keep-alives are present as this
is called after a keep-alive request finishes but before the next request.
=head2 post_read_request
Params: HEADER
lib/AxKit2/Plugin.pm view on Meta::CPAN
=item * C<DECLINED/OK> - Use default keep-alive response depending on request
type.
=item * C<DONE> - Request was OK, but don't keep the connection open.
=item * Anything Else - ... TBD.
=back
=head2 disconnect
TBD
=head2 error
Params: ERROR
Called whenever a hook C<die()>s or returns C<SERVER_ERROR>.
Return Value:
=over 4
=item * C<DECLINED> - Use default error handler
=item * C<OK/DONE> - Error was sent to browser. Ignore.
=item * Anything Else - Send a different error to the browser.
=back
=head1 CONTINUATIONS
AxKit2 is entirely single threaded, and so it is important not to do things that
take significant runtime away from the main event loop. A simple example of this
might be looking up a request on a remote web server - while the AxKit process
waits for the response it is important to allow AxKit to continue on processing
other requests.
In order to achieve this AxKit2 uses a simplified version of a technique known
in computer science terms as a I<continuation>.
In simple english, this is a way to suspend execution of one request and
I<continue> it at an arbitrary later time.
AxKit2 has a form of continuations based on the core event loop. Some hooks can
suspend execution by returning C<CONTINUATION>, and have execution of the
request continue when some event has occured.
A typical usage of this is when you need to perform an action that may take some
time. An example of this is disk I/O - typical I/O in the common POSIX
read/write style APIs occurs in a blocking manner - when you ask for a C<read()>
the disk seeks to the position you need it to go to when it can do so and the
read is performed as soon as possible before the API call returns. This may take
very little CPU time because the OS has to wait until the disk head is in the
correct position to perform the actions requested. But it does take "clock" time
which can be put to better use responding to other requests.
In asynchronous I/O the action is requested and a callback is provided to
be called when the action has occured. This allows the event loop to continue
processing other requests while we are waiting for the disk.
This is better explained with a simple example. For this example we'll take the
C<stat()> system call in an attempt to find out if the filename we are
requesting is a directory or not. In perl we would normally perform this with
the following code:
sub hook_response {
my $self = shift;
my $filename = $self->client->headers_in->filename;
if (-d $filename) {
....
}
$self->do_something_else();
return OK;
}
However with AIO and continuations we can re-write that as:
sub hook_response1 {
my $self = shift;
my $client = $self->shift;
my $filename = $self->client->headers_in->filename;
IO::AIO::aio_stat $filename, sub {
if (-d _) {
...
}
$self->do_something_else();
$client->finish_continuation;
};
return CONTINUATION;
}
sub hook_response2 {
return DECLINED;
}
A first read will prove one thing - AIO and continuations are a I<lot> harder
than regular procedural code. However often the performance benefits are worth
it.
In general if you need to use continuations then consult the plugins in the
F<aio/> directory, and send emails to the mailing list, as they are generally
a big source of hard to locate bugs.
=head1 SEE ALSO
L<AxKit2::Connection>
L<AxKit2::HTTPHeaders>
L<AxKit2::Constants>
L<AxKit2::Processor>
=cut
( run in 1.410 second using v1.01-cache-2.11-cpan-39bf76dae61 )