You are viewing a plain text version of this content. The canonical link for it is here.
Posted to docs-cvs@perl.apache.org by st...@apache.org on 2005/05/10 06:20:31 UTC

svn commit: r169415 - /perl/modperl/docs/trunk/src/docs/2.0/user/handlers/filters.pod

Author: stas
Date: Mon May  9 21:20:29 2005
New Revision: 169415

URL: http://svn.apache.org/viewcvs?rev=169415&view=rev
Log:
new section: Setting the Content-Length Header in Request Output Filters

Modified:
    perl/modperl/docs/trunk/src/docs/2.0/user/handlers/filters.pod

Modified: perl/modperl/docs/trunk/src/docs/2.0/user/handlers/filters.pod
URL: http://svn.apache.org/viewcvs/perl/modperl/docs/trunk/src/docs/2.0/user/handlers/filters.pod?rev=169415&r1=169414&r2=169415&view=diff
==============================================================================
--- perl/modperl/docs/trunk/src/docs/2.0/user/handlers/filters.pod (original)
+++ perl/modperl/docs/trunk/src/docs/2.0/user/handlers/filters.pod Mon May  9 21:20:29 2005
@@ -2535,6 +2535,93 @@
 
 
 
+=head2 Setting the Content-Length Header in Request Output Filters
+
+Earlier we have stated that a filter that modifies the content's
+length must unset the Content-Length HTTP header. However sometimes
+it's desirable to have this header set, for example when dealing with
+proxies. Since the headers are sent before the data, all the data must
+be first buffered and processed. You cannot accomplish this task with
+the streaming filter API since it passes FLUSH buckets through. As
+soon as the FLUSH bucket is received by the core filter that sends the
+headers, it generates the headers and sends those out. Therefore the
+bucket brigade API must be used here to have a complete control over
+what's going through. Here is a possible implementation:
+
+  #file:MyApache2/FilterChangeLength.pm
+  #-------------------------------------
+  package MyApache2::FilterChangeLength;
+  
+  use strict;
+  use warnings FATAL => 'all';
+  
+  use Apache2::RequestRec ();
+  
+  use APR::Table ();
+  use APR::Bucket ();
+  use APR::Brigade ();
+  
+  use base qw(Apache2::Filter);
+  
+  use Apache2::Const -compile => qw(OK);
+  use APR::Const     -compile => ':common';
+  
+  sub handler {
+      my($filter, $bb) = @_;
+  
+      my $ctx = $filter->ctx;
+  
+      # no need to unset the C-L header, since this filter makes sure to
+      # correct it before any headers go out.
+      #unless ($ctx) {
+      #    $filter->r->headers_out->unset('Content-Length');
+      #}
+  
+      my $data = exists $ctx->{data} ? $ctx->{data} : '';
+      $ctx->{invoked}++;
+      my($bdata, $seen_eos) = flatten_bb($bb);
+      $bdata =~ s/-//g;
+      $data .= $bdata if $bdata;
+  
+      if ($seen_eos) {
+          my $len = length $data;
+          $filter->r->headers_out->set('Content-Length', $len);
+          $filter->print($data) if $data;
+      }
+      else {
+          # store context for all but the last invocation
+          $ctx->{data} = $data;
+          $filter->ctx($ctx);
+      }
+  
+      return Apache2::Const::OK;
+  }
+  
+  sub flatten_bb {
+      my ($bb) = shift;
+  
+      my $seen_eos = 0;
+  
+      my @data;
+      for (my $b = $bb->first; $b; $b = $bb->next($b)) {
+          $seen_eos++, last if $b->is_eos;
+          $b->read(my $bdata);
+          push @data, $bdata;
+      }
+      return (join('', @data), $seen_eos);
+  }
+  
+  1;
+
+In this module we use flatten_bb() to read the data from the buckets
+and signal when the EOS is received. The filter simply collects the
+data, storing it in the filter context. When it receives EOS it sets
+the C<Content-Length> header and sends the data out.
+
+
+
+
+
 
 =head1 Filter Tips and Tricks
 



---------------------------------------------------------------------
To unsubscribe, e-mail: docs-cvs-unsubscribe@perl.apache.org
For additional commands, e-mail: docs-cvs-help@perl.apache.org