stas 2002/11/19 16:36:39 Modified: src/docs/2.0/user/handlers filters.pod Log: - fix the FilterSnoop example to dump the sniffed data as soon as it's available to - update the output/explanations to reflect the reality, which changes daily Revision Changes Path 1.6 +77 -64 modperl-docs/src/docs/2.0/user/handlers/filters.pod Index: filters.pod =================================================================== RCS file: /home/cvs/modperl-docs/src/docs/2.0/user/handlers/filters.pod,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- filters.pod 17 Nov 2002 05:29:11 -0000 1.5 +++ filters.pod 20 Nov 2002 00:36:38 -0000 1.6 @@ -240,10 +240,11 @@ use strict; use warnings; + use APR::Bucket (); + use base qw(Apache::Filter); use Apache::FilterRec (); use APR::Brigade (); - use APR::Bucket (); use Apache::Const -compile => qw(OK DECLINED); use APR::Const -compile => ':common'; @@ -259,45 +260,44 @@ my $stream = defined $mode ? "input" : "output"; # read the data and pass-through the bucket brigades unchanged - my $ra_data = ''; if (defined $mode) { # input filter my $rv = $filter->next->get_brigade($bb, $mode, $block, $readbytes); return $rv unless $rv == APR::SUCCESS; - $ra_data = bb_sniff($bb); + bb_dump($type, $stream, $bb); } else { # output filter - $ra_data = bb_sniff($bb); + bb_dump($type, $stream, $bb); my $rv = $filter->next->pass_brigade($bb); return $rv unless $rv == APR::SUCCESS; } - # send the sniffed info to STDERR so not to interfere with normal - # output - my $direction = $stream eq 'output' ? ">>>" : "<<<"; - print STDERR "\n$direction $type $stream filter\n"; - my $c = 1; - while (my($btype, $data) = splice @$ra_data, 0, 2) { - print STDERR " o bucket $c: $btype\n"; - print STDERR "[$data]\n"; - $c++; - } - return Apache::OK; } - sub bb_sniff { - my $bb = shift; + sub bb_dump { + my($type, $stream, $bb) = @_; + my @data; for (my $b = $bb->first; $b; $b = $bb->next($b)) { $b->read(my $bdata); $bdata = '' unless defined $bdata; push @data, $b->type->name, $bdata; } - return [EMAIL PROTECTED]; - } + # send the sniffed info to STDERR so not to interfere with normal + # output + my $direction = $stream eq 'output' ? ">>>" : "<<<"; + print STDERR "\n$direction $type $stream filter\n"; + + my $c = 1; + while (my($btype, $data) = splice @data, 0, 2) { + print STDERR " o bucket $c: $btype\n"; + print STDERR "[$data]\n"; + $c++; + } + } 1; This package provides two filter handlers, one for connection and @@ -318,20 +318,18 @@ passed, whereas the arguments C<$mode>, C<$block>, and C<$readbytes> are passed only to input filter handlers. -If we are in the input mode, we retrieve the bucket brigade and -immediately link it to C<$bb> which makes the brigade available to the -next filter. When this filter handler returns, the next filter on the -stack will get the brigade. If we forget to perform this linking our -filter will become a black hole in which data simply disappears. Next -we call C<bb_sniff()> which returns the type and the content of the -buckets in the brigade. - -If we are in the output mode, C<$bb> already points to the current -bucket brigade. Therefore we can read the contents of the brigade -right away. After that we pass the brigade to the next filter. - -Finally we dump to STDERR the information about the type of the -current mode, and the content of the bucket bridge. +If we are in the input mode, in the same call we retrieve the bucket +brigade from the previous filter on the input filters stack and +immediately link it to the C<$bb> variable which makes the bucket +brigade available to the next input filter when the filter handler +returns. If we forget to perform this linking our filter will become a +black hole in which data simply disappears. Next we call C<bb_dump()> +which dumps the type of the filter and the contents of the bucket +brigade to C<STDERR>, without influencing the normal data flow. + +If we are in the output mode, the C<$bb> variable already points to +the current bucket brigade. Therefore we can read the contents of the +brigade right away. After that we pass the brigade to the next filter. Let's snoop on connection and request filter levels in both directions by applying the following configuration: @@ -439,13 +437,9 @@ filter is of type I<EOS>, meaning that all the input data from the current request has been received. -META: that's not true anymore, Apache now doesn't set CL header for -dynamic content, so there is no setaside. Need to adjust the section -for this change. - Next we can see that C<MyApache::Dump::handler> has generated its -response. However only the request output filter is filtering it at -this point: +response. However we can see that only the request output filter gets +run at this point: >>> request output filter o bucket 1: TRANSIENT @@ -456,45 +450,66 @@ ] This happens because Apache hasn't sent yet the response HTTP headers -to the client. Apache postpones the header sending so it can calculate -and set the C<Content-Length> header. This time the brigade consists -of a single bucket of type I<TRANSIENT> which is allocated from the -stack memory, which will eventually be converted to the I<HEAP> type, -before the body of the response is sent to the client. - -When the content handler returns Apache sends the HTTP headers through -connection output filters (notice that the request output filters -don't see it): +to the client. The request filter sees a bucket brigade with a single +bucket of type I<TRANSIENT> which is allocated from the stack memory. + +The moment the first bucket brigade of the response body has entered +the connection output filters, Apache injects a bucket brigade with +the HTTP headers. Therefore we can see that the connection output +filter is filtering the bridage with HTTP headers (notice that the +request output filters don't see it): >>> connection output filter o bucket 1: HEAP [HTTP/1.1 200 OK - Date: Wed, 14 Aug 2002 07:31:53 GMT - Server: Apache/2.0.41-dev (Unix) mod_perl/1.99_05-dev - Perl/v5.8.0 mod_ssl/2.0.41-dev OpenSSL/0.9.6d DAV/2 - Content-Length: 42 + Date: Tue, 19 Nov 2002 15:59:32 GMT + Server: Apache/2.0.44-dev (Unix) mod_perl/1.99_08-dev + Perl/v5.8.0 mod_ssl/2.0.44-dev OpenSSL/0.9.6d DAV/2 Connection: close + Transfer-Encoding: chunked Content-Type: text/plain; charset=ISO-8859-1 ] -Now the response body in the bucket of type I<HEAP> is passed through -the connection output filter, followed by the I<EOS> bucket to mark -the end of the request: +and followed by the first response body's brigade: >>> connection output filter - o bucket 1: HEAP + o bucket 1: TRANSIENT + [2b + ] + o bucket 2: TRANSIENT [args: foo=1&bar=2 content: mod_perl rules + + ] + o bucket 3: IMMORTAL + [ ] - o bucket 2: EOS - [] -Finally the output is flushed, to make sure that any buffered output -is sent to the client: +If the response is large, the request and connection filters will +filter chunks of the response one by one. +META: what's the size of the chunks? 8k? + +Finally, Apache sends a series of the bucket brigades to finish off +the response, including the end of stream meta-bucket to tell filters +that they shouldn't expect any more data, and flush buckets to flush +the data, to make sure that any buffered output is sent to the client: + + >>> connection output filter + o bucket 1: IMMORTAL + [0 + + ] + o bucket 2: EOS + [] + + >>> connection output filter + o bucket 1: FLUSH + [] + >>> connection output filter o bucket 1: FLUSH [] @@ -503,10 +518,8 @@ many time during each request and connection. It's called for each bucket brigade. -Also it's important to notice that the request input filter is called -only if there is some POSTed data to read, if you run the same request -without POSTing any data or simply running a GET request, the request -input filter won't be called. +Also it's important to notice that request input filters are called +only if there is some POSTed data to read. =head1 Input Filters
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]