stas        2002/08/27 02:48:59

  Modified:    src/docs/2.0/user/handlers handlers.pod
  Log:
  - more filter examples tweaks
  - add PerlPostReadRequestHandler example
  
  Revision  Changes    Path
  1.13      +229 -55   modperl-docs/src/docs/2.0/user/handlers/handlers.pod
  
  Index: handlers.pod
  ===================================================================
  RCS file: /home/cvs/modperl-docs/src/docs/2.0/user/handlers/handlers.pod,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- handlers.pod      22 Aug 2002 11:26:42 -0000      1.12
  +++ handlers.pod      27 Aug 2002 09:48:59 -0000      1.13
  @@ -218,9 +218,10 @@
   I<error_log>, and therefore any messages to that stream will be
   printed to the console the server is starting from (if such exists).
   
  -This phase is of type C<RUN_ALL>.
  +This phase is of type C<L<RUN_ALL|/item_RUN_ALL>>.
   
  -The handler's configuration scope is C<SRV>.
  +The handler's configuration scope is
  +C<L<SRV|docs::2.0::user::config::config/item_SRV>>.
   
   As we have seen in the C<MyApache::StartupLog::open_logs> handler, the
   I<open_logs> phase handlers accept four arguments: the configuration
  @@ -265,9 +266,10 @@
   
   META: once mod_perl will have the API for that.
   
  -This phase is of type C<RUN_ALL>.
  +This phase is of type C<L<RUN_ALL|/item_RUN_ALL>>.
   
  -The handler's configuration scope is C<SRV>.
  +The handler's configuration scope is
  +C<L<SRV|docs::2.0::user::config::config/item_SRV>>.
   
   In our C<MyApache::StartupLog> example we used the I<post_config()>
   handler:
  @@ -299,9 +301,10 @@
   C<Apache::DBI> pre-opens database connections during this phase and
   C<Apache::Resource> sets the process' resources limits.
   
  -This phase is of type C<VOID>.
  +This phase is of type C<L<VOID|/item_VOID>>.
   
  -The handler's configuration scope is C<SRV>.
  +The handler's configuration scope is
  +C<L<SRV|docs::2.0::user::config::config/item_SRV>>.
   
   In our C<MyApache::StartupLog> example we used the I<child_init()>
   handler:
  @@ -441,10 +444,11 @@
   interpreter won't be available to other threads while the images are
   being served.
   
  -This phase is of type C<RUN_ALL>.
  +This phase is of type C<L<RUN_ALL|/item_RUN_ALL>>.
   
  -The handler's configuration scope is C<SRV>, because it's not known
  -yet which resource the request will be mapped to.
  +The handler's configuration scope is
  +C<L<SRV|docs::2.0::user::config::config/item_SRV>>, because it's not
  +known yet which resource the request will be mapped to.
   
   XXX: As of this moment C<PerlPreConnectionHandler> is not being
   executed by mod_perl. Stay tuned.
  @@ -469,11 +473,12 @@
   processing with processing for some other protocols (e.g., POP3, FTP,
   etc.).
   
  -This phase is of type C<RUN_FIRST>.
  +This phase is of type C<L<RUN_FIRST|/item_RUN_FIRST>>.
   
  -The handler's configuration scope is C<SRV>. Therefore the only way to
  -run protocol servers different than the core HTTP is inside dedicated
  -virtual hosts.
  +The handler's configuration scope is
  +C<L<SRV|docs::2.0::user::config::config/item_SRV>>. Therefore the only
  +way to run protocol servers different than the core HTTP is inside
  +dedicated virtual hosts.
   
   A I<process_connection> handler accepts a connection record object as
   its only argument, a socket object can be retrieved from the
  @@ -616,7 +621,7 @@
   
   And try the new connection handler in action:
   
  -  panic% telnet localhost 8010
  +  panic% telnet localhost 8011
     Trying 127.0.0.1...
     Connected to localhost (127.0.0.1).
     Escape character is '^]'.
  @@ -633,7 +638,7 @@
   connection and the filter handlers.
   
     file:MyApache/EchoBB.pm
  -  -------------------
  +  -----------------------
     package MyApache::EchoBB;
     
     use strict;
  @@ -774,7 +779,9 @@
   Those familiar with mod_perl 1.0 will find the HTTP request cycle in
   mod_perl 2.0 to be almost identical to the mod_perl 1.0's model. The
   only difference is in the I<response> phase which now includes
  -filtering.
  +filtering. Also the C<PerlHandler> directive has been renamed to
  +C<PerlResponseHandler> to better match the corresponding Apache phase
  +name (I<response>).
   
   The following diagram depicts the HTTP request life cycle and
   highlights which handlers are available to mod_perl 2.0:
  @@ -833,13 +840,77 @@
   This phase is usually used to do processings that must happen once per
   request.
   
  -This phase is of type C<RUN_ALL>.
  +This phase is of type C<L<RUN_ALL|/item_RUN_ALL>>.
   
  -The handler's configuration scope is C<SRV>, because at this phase the
  -request has not yet been associated with a particular filename or
  -directory.
  +The handler's configuration scope is
  +C<L<SRV|docs::2.0::user::config::config/item_SRV>>, because at this
  +phase the request has not yet been associated with a particular
  +filename or directory.
  +
  +Consider the following registry script:
  +
  +  touch.pl
  +  --------
  +  use strict;
  +  use warnings;
  +  
  +  use Apache::ServerUtil ();
  +  use File::Spec::Functions qw(catfile);
  +  
  +  my $r = shift;
  +  $r->content_type('text/plain');
  +  
  +  my $conf_file = catfile Apache::server_root_relative($r->pool, 'conf'),
  +      "httpd.conf";
  +  
  +  printf "$conf_file is %0.2f minutes old", 60*24*(-M $conf_file);
  +
  +This registry script is supposed to print when the last time
  +I<httpd.conf> has been modified. If you run this script several times
  +you might be surprised that it reports the same thing all the
  +time. Unless you happen to hit a recently started child process which
  +will then report a different value.
  +
  +This happens because the C<-M> operator reports the difference between
  +file's modification time and the value of a special perl variable
  +C<$^T>. When we run scripts from the command line, this variable is
  +always set to the time when the script gets invoked. Under mod_perl
  +this variable is getting preset once when the child process starts and
  +doesn't change since then, so all requests see the same time
  +
  +Armed with this knowledge, in order to make our code behave like the
  +command line programs we need to reset C<$^T> to the request's start
  +time, before C<-M> is used. We can change the script itself, but what
  +if we need to do the same change for several other scripts and
  +handlers? A simple C<PerlPostReadRequestHandler> handler, which will
  +be executed as the very first thing of each requests, comes handy
  +here:
  +
  +  package MyApache::TimeReset;
  +  
  +  use Apache::RequestRec ();
  +  
  +  use Apache::Const -compile => 'OK';
  +  
  +  sub handler {
  +      my $r = shift;
  +      $^T = $r->request_time;
  +      return Apache::OK;
  +  }
  +  1;
  +
  +We could do:
  +
  +  $^T = time();
  +
  +But to make things more efficient we use C<$r-E<gt>request_time> which
  +already stores the request's start time, and returns it without doing
  +an additional system call.
  +
  +To enable it just add to I<httpd.conf>:
  +
  +  PerlPostReadRequestHandler MyApache::TimeReset
   
  -Example:
   
   =head2 PerlTransHandler
   
  @@ -853,11 +924,12 @@
   If no custom handlers is provided, the server's default rules
   (C<Alias> directives and the like) will continue to be followed.
   
  -This phase is of type C<RUN_FIRST>.
  +This phase is of type C<L<RUN_FIRST|/item_RUN_FIRST>>.
   
  -The handler's configuration scope is C<SRV>, because at this phase the
  -request has not yet been associated with a particular filename or
  -directory.
  +The handler's configuration scope is
  +C<L<SRV|docs::2.0::user::config::config/item_SRV>>, because at this
  +phase the request has not yet been associated with a particular
  +filename or directory.
   
   Example:
   
  @@ -871,7 +943,7 @@
   
   It is the first handler to be invoked when serving a request.
   
  -This phase is of type C<RUN_ALL>.
  +This phase is of type C<L<RUN_ALL|/item_RUN_ALL>>.
   
   Example:
   
  @@ -887,9 +959,10 @@
   can be used to block evil clients, while little resources were wasted
   on these.
   
  -This phase is of type C<RUN_ALL>.
  +This phase is of type C<L<RUN_ALL|/item_RUN_ALL>>.
   
  -The handler's configuration scope is C<DIR>.
  +The handler's configuration scope is
  +C<L<DIR|docs::2.0::user::config::config/item_DIR>>.
   
   Example:
   
  @@ -906,9 +979,10 @@
   time of the day or any other rule not connected to the user's
   identity.
   
  -This phase is of type C<RUN_ALL>.
  +This phase is of type C<L<RUN_ALL|/item_RUN_ALL>>.
   
  -The handler's configuration scope is C<DIR>.
  +The handler's configuration scope is
  +C<L<DIR|docs::2.0::user::config::config/item_DIR>>.
   
   Example:
   
  @@ -928,9 +1002,10 @@
   browser will normally pop up a dialog box that prompts the user for
   login information.
   
  -This phase is of type C<RUN_FIRST>.
  +This phase is of type C<L<RUN_FIRST|/item_RUN_FIRST>>.
   
  -The handler's configuration scope is C<DIR>.
  +The handler's configuration scope is
  +C<L<DIR|docs::2.0::user::config::config/item_DIR>>.
   
   =head2 PerlAuthzHandler
   
  @@ -947,9 +1022,10 @@
   C<AUTH_REQUIRED> to indicate that the user is not authorized to access
   the requested document.
   
  -This phase is of type C<RUN_FIRST>.
  +This phase is of type C<L<RUN_FIRST|/item_RUN_FIRST>>.
   
  -The handler's configuration scope is C<DIR>.
  +The handler's configuration scope is
  +C<L<DIR|docs::2.0::user::config::config/item_DIR>>.
   
   Example:
   
  @@ -966,9 +1042,10 @@
   
   Of course later phases may override the mime type set in this phase.
   
  -This phase is of type C<RUN_FIRST>.
  +This phase is of type C<L<RUN_FIRST|/item_RUN_FIRST>>.
   
  -The handler's configuration scope is C<DIR>.
  +The handler's configuration scope is
  +C<L<DIR|docs::2.0::user::config::config/item_DIR>>.
   
   Example:
   
  @@ -982,9 +1059,10 @@
   environment with variables configured with I<SetEnv> and I<PassEnv>
   directives.
   
  -This phase is of type C<RUN_ALL>.
  +This phase is of type C<L<RUN_ALL|/item_RUN_ALL>>.
   
  -The handler's configuration scope is C<DIR>.
  +The handler's configuration scope is
  +C<L<DIR|docs::2.0::user::config::config/item_DIR>>.
   
   Example:
   
  @@ -999,7 +1077,7 @@
   mod_perl. For example:
   
     <Location /perl>
  -     SetHandler  perl-script
  +     SetHandler perl-script
        PerlResponseHandler Apache::Registry
     </Location>
   
  @@ -1007,9 +1085,10 @@
   response generation. C<PerlResponseHandler> tells mod_perl which
   handler is going to do the job.
   
  -This phase is of type C<RUN_FIRST>.
  +This phase is of type C<L<RUN_FIRST|/item_RUN_FIRST>>.
   
  -The handler's configuration scope is C<DIR>.
  +The handler's configuration scope is
  +C<L<DIR|docs::2.0::user::config::config/item_DIR>>.
   
   Example:
   
  @@ -1028,9 +1107,10 @@
   information in various ways (e.g., logging to a flat file or a
   database).
   
  -This phase is of type C<RUN_ALL>.
  +This phase is of type C<L<RUN_ALL|/item_RUN_ALL>>.
   
  -The handler's configuration scope is C<DIR>.
  +The handler's configuration scope is
  +C<L<DIR|docs::2.0::user::config::config/item_DIR>>.
   
   Example:
   
  @@ -1043,6 +1123,13 @@
   The handler's configuration scope is C<XXX>.
   
   
  +
  +
  +
  +
  +
  +
  +
   =head1 I/O Filtering
   
   Apache 2.0 considers all incoming and outgoing data as chunks of
  @@ -1135,7 +1222,8 @@
   This accomplishes the configuration of the connection input and output
   filters.
   
  -[META: 
  +[META: This belongs to the Apache::Filter manpage and should be moved
  +there when this page is created.
   
   Inside a connection filter the current connection object can be
   retrieved with:
  @@ -1147,9 +1235,6 @@
   
     my $r = $filter->r;
   
  -This belongs to the Apache::Filter manpage and should be moved there
  -when this page is created.
  -
   ]
   
   mod_perl provides two interfaces to filtering: a direct bucket
  @@ -1164,9 +1249,10 @@
   The C<PerlInputFilterHandler> handler registers a filter for input
   filtering.
   
  -This handler is of type C<VOID>.
  +This handler is of type C<L<VOID|/item_VOID>>.
   
  -The handler's configuration scope is C<DIR>.
  +The handler's configuration scope is
  +C<L<DIR|docs::2.0::user::config::config/item_DIR>>.
   
   The following sections include several examples of the
   C<PerlInputFilterHandler> handler.
  @@ -1176,9 +1262,10 @@
   The C<PerlOutputFilterHandler> handler registers and configures output
   filters.
   
  -This handler is of type C<VOID>.
  +This handler is of type C<L<VOID|/item_VOID>>.
   
  -The handler's configuration scope is C<DIR>.
  +The handler's configuration scope is
  +C<L<DIR|docs::2.0::user::config::config/item_DIR>>.
   
   The following sections include several examples of the
   C<PerlOutputFilterHandler> handler.
  @@ -1693,8 +1780,89 @@
   that's why the content length is reported as 25 and not 24 as in the
   real GET request.
   
  +
  +
   =head2 Request Input Filter
   
  +Request filters are really non-different from connection filters,
  +other than that they are working on request and response bodies and
  +have an access to a request object. The filter implementation is
  +pretty much identical. Let's look at the request input filter that
  +lowercases the request's body C<MyApache::InputRequestFilterLC>:
  +
  +  file:MyApache/InputRequestFilterLC.pm
  +  -------------------------------------
  +  package MyApache::InputRequestFilterLC;
  +  
  +  use strict;
  +  use warnings;
  +  
  +  use base qw(Apache::Filter);
  +  
  +  use APR::Brigade ();
  +  use APR::Bucket ();
  +  
  +  use Apache::Const -compile => 'OK';
  +  use APR::Const -compile => ':common';
  +  
  +  sub handler : FilterRequestHandler {
  +      my($filter, $bb, $mode, $block, $readbytes) = @_;
  +  
  +      my $c = $filter->c;
  +      my $bb_ctx = APR::Brigade->new($c->pool, $c->bucket_alloc);
  +      my $rv = $filter->next->get_brigade($bb_ctx, $mode, $block, 
$readbytes);
  +      return $rv unless $rv == APR::SUCCESS;
  +  
  +      while (!$bb_ctx->empty) {
  +          my $b = $bb_ctx->first;
  +  
  +          $b->remove;
  +  
  +          if ($b->is_eos) {
  +              $bb->insert_tail($b);
  +              last;
  +          }
  +  
  +          my $data;
  +          my $status = $b->read($data);
  +          return $status unless $status == APR::SUCCESS;
  +  
  +          $b = APR::Bucket->new(lc $data) if $data;
  +  
  +          $bb->insert_tail($b);
  +      }
  +  
  +      Apache::OK;
  +  }
  +  
  +  1;
  +
  +Now if we use the C<MyApache::Dump> response handler, we have
  +developed before in this chapter, which dumps the query string and the
  +content body as a response, and configure the server as follows:
  +
  +  <Location /lc_input>
  +      SetHandler modperl
  +      PerlResponseHandler    +MyApache::Dump
  +      PerlInputFilterHandler +MyApache::InputRequestFilterLC
  +  </Location>
  +
  +When issuing a POST request:
  +
  + % echo "mOd_pErl RuLeS" | POST 
'http://localhost:8002/dump_input?FoO=1&BAR=2'
  +
  +we get a response:
  +
  +  args:
  +  FoO=1&BAR=2
  +  content:
  +  mod_perl rules
  +
  +indeed we can see that our filter has lowercased the POSTed body,
  +before the content handler received it. You can see that the query
  +string wasn't changed.
  +
  +
   =head2 Bucket Brigades and Stream-Oriented Request Output Filters
   
   As mentioned earlier output filters can be written using the bucket
  @@ -1853,7 +2021,7 @@
         my($filter, $bb) = @_;
     
         my $c = $filter->c;
  -      my $new_bb = APR::Brigade->new($c->pool, $c->bucket_alloc);
  +      my $bb_ctx = APR::Brigade->new($c->pool, $c->bucket_alloc);
     
         while (!$bb->empty) {
             my $bucket = $bb->first;
  @@ -1861,7 +2029,7 @@
             $bucket->remove;
     
             if ($bucket->is_eos) {
  -              $new_bb->insert_tail($bucket);
  +              $bb_ctx->insert_tail($bucket);
                 last;
             }
     
  @@ -1875,10 +2043,10 @@
                 $bucket = APR::Bucket->new($data);
             }
     
  -          $new_bb->insert_tail($bucket);
  +          $bb_ctx->insert_tail($bucket);
         }
     
  -      my $rv = $filter->next->pass_brigade($new_bb);
  +      my $rv = $filter->next->pass_brigade($bb_ctx);
         return $rv unless $rv == APR::SUCCESS;
     
         Apache::OK;
  @@ -1917,6 +2085,8 @@
   of the new bucket brigade and break the loop. Finally we pass the
   created brigade with modified data to the next filter and return.
   
  +
  +
   =head2 Filter Tips
   
   Various tips to use in filters.
  @@ -1934,6 +2104,10 @@
   
   Request filters have an access to the request object, so we simply
   modify it.
  +
  +
  +
  +
   
   
   =head1 Handler (Hook) Types
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to