The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

MPMinus::BaseHandlers - Base handlers of MPMinus

VERSION

Version 1.03

SYNOPSIS

    package MPM::foo::Handlers;
    use strict;

    use MPMinus;
    use base qw/MPMinus::BaseHandlers/;
    
    sub new { bless {}, __PACKAGE__ }
    sub handler {
        my $r = shift;
        my $m = MPMinus->m;
        $m->conf_init($r, __PACKAGE__);
        __PACKAGE__->Init($m);

        # Handlers
        $r->handler('modperl'); # modperl, perl-script
        
        $r->set_handlers(PerlHeaderParserHandler => sub { __PACKAGE__->HeaderParserHandler($m) });
        $r->set_handlers(PerlAccessHandler => sub { __PACKAGE__->AccessHandler($m) });
        $r->set_handlers(PerlAuthenHandler => sub { __PACKAGE__->AuthenHandler($m) });
        $r->set_handlers(PerlAuthzHandler => sub { __PACKAGE__->AuthzHandler($m) });
        $r->set_handlers(PerlTypeHandler => sub { __PACKAGE__->TypeHandler($m) });
        $r->set_handlers(PerlFixupHandler => sub { __PACKAGE__->FixupHandler($m) });
        $r->set_handlers(PerlResponseHandler => sub { __PACKAGE__->ResponseHandler($m) });
        $r->set_handlers(PerlLogHandler => sub { __PACKAGE__->LogHandler($m) });
        $r->set_handlers(PerlCleanupHandler => sub { __PACKAGE__->CleanupHandler($m) });
        
        return __PACKAGE__->InitHandler($m);
    }
    sub InitHandler {
        my $pkg = shift;
        my $m = shift;

        # ... Setting Nodes ...
        # $m->set( nodename => ' ... value ... ' ) unless $m->nodename;
        
        ...

        return __PACKAGE__->SUPER::InitHandler($m);
    }

DESCRIPTION

Base handlers of MPMinus.

See http://perl.apache.org/docs/2.0/user/handlers/intro.html

METHODS

Init
    sub handler {
        my $r = shift;
        my $m = MPMinus->m;
        $m->conf_init($r, __PACKAGE__);
        __PACKAGE__->Init($m);
        
        ...
    }

NOTE: This is a required module call of MPM::foo::Handlers

SERVER LIFE CYCLE HANDLERS

OpenLogsHandler
    PerlModule            MPM::foo::Handlers
    PerlOpenLogsHandler   MPM::foo::Handlers::OpenLogs
    
    sub OpenLogs {
        my ($conf_pool, $log_pool, $temp_pool, $s) = @_;
        say("process $$ is born to reproduce");
        return Apache2::Const::OK;
    }

The open_logs phase happens just before the post_config phase.

Handlers registered by PerlOpenLogsHandler are usually used for opening module-specific log files (e.g., httpd core and mod_ssl open their log files during this phase).

At this stage the STDERR stream is not yet redirected to error_log, and therefore any messages to that stream will be printed to the console the server is starting from (if such exists).

    Type  : RUN_ALL
    Scope : SRV

See http://perl.apache.org/docs/2.0/user/handlers/server.html

PostConfigHandler
    PerlModule            MPM::foo::Handlers
    PerlPostConfigHandler MPM::foo::Handlers::PostConfig

    sub PostConfig {
        my ($conf_pool, $log_pool, $temp_pool, $s) = @_;
        say("configuration is completed");
        return Apache2::Const::OK;
    }

The post_config phase happens right after Apache has processed the configuration files, before any child processes were spawned (which happens at the child_init phase).

This phase can be used for initializing things to be shared between all child processes. You can do the same in the startup file, but in the post_config phase you have an access to a complete configuration tree (via Apache2::Directive).

    Type  : RUN_ALL
    Scope : SRV

See http://perl.apache.org/docs/2.0/user/handlers/server.html

ChildInitHandler
    PerlModule            MPM::foo::Handlers
    PerlChildInitHandler  MPM::foo::Handlers::ChildInit

    sub ChildInit {
        my ($child_pool, $s) = @_;
        say("process $$ is born to serve");
        return Apache2::Const::OK;
    }

The child_init phase happens immediately after the child process is spawned. Each child process (not a thread!) will run the hooks of this phase only once in their life-time.

In the prefork MPM this phase is useful for initializing any data structures which should be private to each process. For example Apache::DBI pre-opens database connections during this phase and Apache2::Resource sets the process' resources limits.

    Type  : VOID
    Scope : SRV

See http://perl.apache.org/docs/2.0/user/handlers/server.html

ChildExitHandler
    PerlModule            MPM::foo::Handlers
    PerlChildExitHandler  MPM::foo::Handlers::ChildExit

    sub ChildExit {
        my ($child_pool, $s) = @_;
        my $m = MPMinus->m;
        say("process $$ now exits");
        return Apache2::Const::OK;
    }

Opposite to the child_init phase, the child_exit phase is executed before the child process exits. Notice that it happens only when the process exits, not the thread (assuming that you are using a threaded mpm).

    Type  : RUN_ALL
    Scope : SRV

See http://perl.apache.org/docs/2.0/user/handlers/server.html

See http://perl.apache.org/docs/2.0/user/handlers/server.html

PROTOCOL HANDLERS

These handlers in this section are not considered. See user's guide http://perl.apache.org/docs/2.0/user/index.html

PerlPreConnectionHandler

The pre_connection phase happens just after the server accepts the connection, but before it is handed off to a protocol module to be served. It gives modules an opportunity to modify the connection as soon as possible and insert filters if needed. The core server uses this phase to setup the connection record based on the type of connection that is being used. mod_perl itself uses this phase to register the connection input and output filters.

In mod_perl 1.0 during code development Apache::Reload was used to automatically reload modified since the last request Perl modules. It was invoked during post_read_request, the first HTTP request's phase. In mod_perl 2.0 pre_connection is the earliest phase, so if we want to make sure that all modified Perl modules are reloaded for any protocols and its phases, it's the best to set the scope of the Perl interpreter to the lifetime of the connection via:

    PerlInterpScope connection

and invoke the Apache2::Reload handler during the pre_connection phase. However this development-time advantage can become a disadvantage in production--for example if a connection, handled by HTTP protocol, is configured as KeepAlive and there are several requests coming on the same connection and only one handled by mod_perl and the others by the default images handler, the Perl interpreter won't be available to other threads while the images are being served.

    Type  : RUN_ALL
    Scope : SRV

See http://perl.apache.org/docs/2.0/user/handlers/protocols.html

PerlProcessConnectionHandler

he process_connection phase is used to process incoming connections. Only protocol modules should assign handlers for this phase, as it gives them an opportunity to replace the standard HTTP processing with processing for some other protocols (e.g., POP3, FTP, etc.).

    Type  : RUN_FIRST
    Scope : SRV

See http://perl.apache.org/docs/2.0/user/handlers/protocols.html

FILTERS

These handlers in this section are not considered. See user's guide, part Input and Output Filters http://perl.apache.org/docs/2.0/user/handlers/filters.html

    # Set up handlers:
    $r->add_input_filter(\&InputFilterHandler);
    $r->add_output_filter(\&OutputFilterHandler);
    
    # Realisation
    sub InputFilterHandler {
        my ($f, $bb, $mode, $block, $readbytes) = @_; # filter args
        #debug(" -- InputFilterHandler N".($f->ctx?$f->ctx:'0')." (".$f->frec->name.")");

        # runs on first invocation
        unless ($f->ctx) {
            $f->ctx(1);
        }
    
        # runs on all invocations
        while ($f->read(my $buffer, 1024)) {
            # process
        }
    
        # runs on the last invocation
        if ($f->seen_eos) {    
            # finalize
        }
        return Apache2::Const::OK;
    }
    sub OutputFilterHandler {
        my ($f, $bb, $mode, $block, $readbytes) = @_; # filter args
        #debug(" -- OutputFilterHandler N".($f->ctx?$f->ctx:'0')." (".$f->frec->name.")");
    
        # runs on first invocation
        if ($f->ctx) {
            $f->ctx( $f->ctx + 1 )
        } else {
            $f->r->headers_out->unset('Content-Length');
            $f->ctx(1);
        }
    
        # runs on all invocations
        while ($f->read(my $buffer, 1024)) {
            $buffer =~ s/\r?\n/<br>/g;
            #$f->print(CP1251toUTF8($buffer));
            $f->print($buffer);
            
        }
    
        # runs on the last invocation
        if ($f->seen_eos) {    
            $f->print('<div style="margin: 10px; padding: 10px; border: solid 1px red;"><b>OUTPUT_FILTER_TEXT_BANNER</b></div>');
        }
        return Apache2::Const::OK;
    }
PerlInputFilterHandler

The PerlInputFilterHandler directive registers a filter, and inserts it into the relevant input filters chain.

    Type  : VOID
    Scope : DIR

See http://perl.apache.org/docs/2.0/user/handlers/filters.html

PerlOutputFilterHandler

The PerlOutputFilterHandler directive registers a filter, and inserts it into the relevant output filters chain.

    Type  : VOID
    Scope : DIR

See http://perl.apache.org/docs/2.0/user/handlers/filters.html

PerlSetInputFilter

The SetInputFilter directive, documented at http://httpd.apache.org/docs-2.0/mod/core.html#setinputfilter, sets the filter or filters which will process client requests and POST input when they are received by the server (in addition to any filters configured earlier).

See http://perl.apache.org/docs/2.0/user/handlers/filters.html

PerlSetOutputFilter

The SetOutputFilter directive, documented at http://httpd.apache.org/docs-2.0/mod/core.html#setoutputfilter sets the filters which will process responses from the server before they are sent to the client (in addition to any filters configured earlier).

See http://perl.apache.org/docs/2.0/user/handlers/filters.html

HTTP PROTOCOL HANDLERS

PostReadRequestHandler
    $r->set_handlers(
            PerlPostReadRequestHandler => 
                sub { __PACKAGE__->PostReadRequestHandler($m) }
        );

The post_read_request phase is the first request phase and happens immediately after the request has been read and HTTP headers were parsed.

This phase is usually used to do processing that must happen once per request. For example Apache2::Reload is usually invoked at this phase to reload modified Perl modules.

    Type  : RUN_ALL
    Scope : SRV

See http://perl.apache.org/docs/2.0/user/handlers/http.html

TransHandler
    $r->set_handlers(
            PerlTransHandler => 
                sub { __PACKAGE__->TransHandler($m) }
        );

The translate phase is used to perform the manipulation of a request's URI. If no custom handler is provided, the server's standard translation rules (e.g., Alias directives, mod_rewrite, etc.) will be used. A PerlTransHandler handler can alter the default translation mechanism or completely override it. This is also a good place to register new handlers for the following phases based on the URI. PerlMapToStorageHandler is to be used to override the URI to filename translation.

    Type  : RUN_FIRST
    Scope : SRV

See http://perl.apache.org/docs/2.0/user/handlers/http.html

MapToStorageHandler
    $r->set_handlers(
            PerlMapToStorageHandler => 
                sub { __PACKAGE__->MapToStorageHandler($m) }
        );

The map_to_storage phase is used to perform the translation of a request's URI into a corresponding filename. If no custom handler is provided, the server will try to walk the filesystem trying to find what file or directory corresponds to the request's URI. Since usually mod_perl handler don't have corresponding files on the filesystem, you will want to shortcut this phase and save quite a few CPU cycles.

    Type  : RUN_FIRST
    Scope : SRV

See http://perl.apache.org/docs/2.0/user/handlers/http.html

InitHandler
    $r->set_handlers(
            PerlInitHandler => 
                sub { __PACKAGE__->InitHandler($m) }
        );

When configured inside any container directive, except <VirtualHost>, this handler is an alias for PerlHeaderParserHandler described earlier. Otherwise it acts as an alias for PerlPostReadRequestHandler described earlier.

It is the first handler to be invoked when serving a request.

    Type  : RUN_ALL

See http://perl.apache.org/docs/2.0/user/handlers/http.html

HeaderParserHandler
    $r->set_handlers(
            PerlHeaderParserHandler => 
                sub { __PACKAGE__->HeaderParserHandler($m) }
        );

The header_parser phase is the first phase to happen after the request has been mapped to its <Location> (or an equivalent container). At this phase the handler can examine the request headers and to take a special action based on these. For example this phase can be used to block evil clients targeting certain resources, while little resources were wasted so far.

    Type  : RUN_ALL
    Scope : DIR

See http://perl.apache.org/docs/2.0/user/handlers/http.html

AccessHandler
    $r->set_handlers(
            PerlAccessHandler => 
                sub { __PACKAGE__->AccessHandler($m) }
        );

The access_checker phase is the first of three handlers that are involved in what's known as AAA: Authentication, Authorization, and Access control.

This phase can be used to restrict access from a certain IP address, time of the day or any other rule not connected to the user's identity.

    Type  : RUN_ALL
    Scope : DIR

See http://perl.apache.org/docs/2.0/user/handlers/http.html

AuthenHandler
    $r->set_handlers(
            PerlAuthenHandler => 
                sub { __PACKAGE__->AuthenHandler($m) }
        );

The check_user_id (authen) phase is called whenever the requested file or directory is password protected. This, in turn, requires that the directory be associated with AuthName, AuthType and at least one require directive.

This phase is usually used to verify a user's identification credentials. If the credentials are verified to be correct, the handler should return Apache2::Const::OK. Otherwise the handler returns Apache2::Const::HTTP_UNAUTHORIZED to indicate that the user has not authenticated successfully. When Apache sends the HTTP header with this code, the browser will normally pop up a dialog box that prompts the user for login information.

    Type  : RUN_FIRST
    Scope : DIR

See http://perl.apache.org/docs/2.0/user/handlers/http.html

AuthzHandler
    $r->set_handlers(
            PerlAuthzHandler => 
                sub { __PACKAGE__->AuthzHandler($m) }
        );

The auth_checker (authz) phase is used for authorization control. This phase requires a successful authentication from the previous phase, because a username is needed in order to decide whether a user is authorized to access the requested resource.

As this phase is tightly connected to the authentication phase, the handlers registered for this phase are only called when the requested resource is password protected, similar to the auth phase. The handler is expected to return Apache2::Const::DECLINED to defer the decision, Apache2::Const::OK to indicate its acceptance of the user's authorization, or Apache2::Const::HTTP_UNAUTHORIZED to indicate that the user is not authorized to access the requested document.

    Type  : RUN_FIRST
    Scope : DIR

See http://perl.apache.org/docs/2.0/user/handlers/http.html

TypeHandler
    $r->set_handlers(
            PerlTypeHandler => 
                sub { __PACKAGE__->TypeHandler($m) }
        );

The type_checker phase is used to set the response MIME type (Content-type) and sometimes other bits of document type information like the document language.

For example mod_autoindex, which performs automatic directory indexing, uses this phase to map the filename extensions to the corresponding icons which will be later used in the listing of files.

Of course later phases may override the mime type set in this phase.

    Type  : RUN_FIRST
    Scope : DIR

See http://perl.apache.org/docs/2.0/user/handlers/http.html

FixupHandler
    $r->set_handlers(
            PerlFixupHandler => 
                sub { __PACKAGE__->FixupHandler($m) }
        );

The fixups phase is happening just before the content handling phase. It gives the last chance to do things before the response is generated. For example in this phase mod_env populates the environment with variables configured with SetEnv and PassEnv directives.

    Type  : RUN_ALL
    Scope : DIR

See http://perl.apache.org/docs/2.0/user/handlers/http.html

ResponseHandler
    $r->set_handlers(
            PerlResponseHandler => 
                sub { __PACKAGE__->ResponseHandler($m) }
        );

The handler (response) phase is used for generating the response. This is arguably the most important phase and most of the existing Apache modules do most of their work at this phase.

This is the only phase that requires two directives under mod_perl.

    Type  : RUN_FIRST
    Scope : DIR

NOTE: This method (ResponseHandler) returns Apache2::Const::NOT_FOUND as default!

See http://perl.apache.org/docs/2.0/user/handlers/http.html

LogHandler
    $r->set_handlers(
            PerlLogHandler => 
                sub { __PACKAGE__->LogHandler($m) }
        );

The log_transaction phase happens no matter how the previous phases have ended up. If one of the earlier phases has aborted a request, e.g., failed authentication or 404 (file not found) errors, the rest of the phases up to and including the response phases are skipped. But this phase is always executed.

By this phase all the information about the request and the response is known, therefore the logging handlers usually record this information in various ways (e.g., logging to a flat file or a database).

    Type  : RUN_ALL
    Scope : DIR

See http://perl.apache.org/docs/2.0/user/handlers/http.html

CleanupHandler
    $r->set_handlers(
            PerlCleanupHandler => 
                sub { __PACKAGE__->CleanupHandler($m) }
        );

There is no cleanup Apache phase, it exists only inside mod_perl. It is used to execute some code immediately after the request has been served (the client went away) and before the request object is destroyed.

There are several usages for this use phase. The obvious one is to run a cleanup code, for example removing temporarily created files. The less obvious is to use this phase instead of PerlLogHandler if the logging operation is time consuming. This approach allows to free the client as soon as the response is sent.

    Type  : RUN_ALL
    Scope : DIR

See http://perl.apache.org/docs/2.0/user/handlers/http.html

See http://perl.apache.org/docs/2.0/user/handlers/http.html

TYPES

VOID

Handlers of the type VOID will be all executed in the order they have been registered disregarding their return values. Though in mod_perl they are expected to return Apache2::Const::OK.

RUN_FIRST

Handlers of the type RUN_FIRST will be executed in the order they have been registered until the first handler that returns something other than Apache2::Const::DECLINED. If the return value is Apache2::Const::DECLINED, the next handler in the chain will be run. If the return value is Apache2::Const::OK the next phase will start. In all other cases the execution will be aborted.

RUN_ALL

Handlers of the type RUN_ALL will be executed in the order they have been registered until the first handler that returns something other than Apache2::Const::OK or Apache2::Const::DECLINED.

For C API declarations see include/ap_config.h, which includes other types which aren't exposed by mod_perl handlers

See http://perl.apache.org/docs/2.0/user/handlers/intro.html

SCOPES

The Scope row shows the location the directives are allowed to appear in:

SRV

Global configuration and <VirtualHost> (mnemonic: SeRVer). These directives are defined as RSRC_CONF in the source code.

DIR

<Directory>, <Location>, <Files> and all their regular expression variants (mnemonic: DIRectory). These directives can also appear in .htaccess files. These directives are defined as OR_ALL in the source code.

These directives can also appear in the global server configuration and <VirtualHost>.

See http://perl.apache.org/docs/2.0/user/config/config.html

AUTHOR

Serz Minus (Lepenkov Sergey) http://serzik.ru <minus@mail333.com>

COPYRIGHT

Copyright (C) 1998-2013 D&D Corporation. All Rights Reserved

LICENSE

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

See LICENSE file