Apache::Filter - Alter the output of previous handlers


  #### In httpd.conf:
  PerlModule Apache::Filter
  # That's it - this isn't a handler.
  <Files ~ "*\.blah">
   SetHandler perl-script
   PerlSetVar Filter On
   PerlHandler Filter1 Filter2 Filter3
  #### In Filter1, Filter2, and Filter3:
  $r = $r->filter_register();  # Required
  my $fh = $r->filter_input(); # Optional (you might not need the input FH)
  while (<$fh>) {
    s/ something / something else /;
  #### or, alternatively:
  $r = $r->filter_register();
  my ($fh, $status) = $r->filter_input(); # Get status information
  return $status unless $status == OK;
  while (<$fh>) {
    s/ something / something else /;


In basic operation, each of the handlers Filter1, Filter2, and Filter3 will make a call to $r->filter_input(), which will return a filehandle. For Filter1, the filehandle points to the requested file. For Filter2, the filehandle contains whatever Filter1 wrote to STDOUT. For Filter3, it contains whatever Filter2 wrote to STDOUT. The output of Filter3 goes directly to the browser.

Note that the modules Filter1, Filter2, and Filter3 are listed in forward order, in contrast to the reverse-order listing of Apache::OutputChain.

When you've got this module, you can use the same handler both as a stand-alone handler, and as an element in a chain. Just make sure that whenever you're chaining, all the handlers in the chain are ``Filter-aware,'' i.e. they each call $r->filter_register() exactly once, before they start printing to STDOUT. There should be almost no overhead for doing this when there's only one element in the chain.

Currently the following public modules are Filter-aware. Please tell me of others you know about.

 Apache::Registry (using Apache::RegistryFilter, included here)


Apache::Filter is a subclass of Apache, so all Apache methods are available.

This module doesn't create an Apache handler class of its own - rather, it adds some methods to the Apache:: class. Thus, it's really a mix-in package that just adds functionality to the $r request object.


In previous releases of this module, it was dangerous to call $r->send_http_header(), because a previous/postvious filter might also try to send headers, and then you'd have duplicate headers getting sent. In current releases you can simply send the headers. If the current filter is the last filter, the headers will be sent as usual, and otherwise send_http_header() is a no-op.


You'll notice in the SYNOPSIS that I say "PerlSetVar Filter On". That information isn't actually used by this module, it's used by modules which are themselves filters (like Apache::SSI). I hereby suggest that filtering modules use this parameter, using it as the switch to detect whether they should call $r->filter_register. However, it's often not necessary - there is very little overhead in simply calling $r->filter_register even when you don't need to do any filtering, and $r->filter_input can be a handy way of opening the $r->filename file.

VERY IMPORTANT: if one handler in a stacked handler chain uses Apache::Filter, then THEY ALL MUST USE IT. This means they all must call $r->filter_register exactly once. Otherwise Apache::Filter couldn't capture the output of the handlers properly, and it wouldn't know when to release the output to the browser.

The output of each filter (except the last) is accumulated in memory before it's passed to the next filter, so memory requirements are large for large pages. Apache::OutputChain only needs to keep one item from print()'s argument list in memory at a time, so it doesn't have this problem, but there are others (each chunk is filtered independently, so content spanning several chunks won't be properly parsed). In future versions I might find a way around this, or cache large pages to disk so memory requirements don't get out of hand. We'll see whether it's a problem.

A couple examples of filters are provided with this distribution in the t/ subdirectory: converts all its input to upper-case, and prints the lines of its input reversed.

Finally, a caveat: in version 0.09 I started explicitly setting the Content-Length to undef. This prevents early filters from incorrectly setting the content length, which will almost certainly be wrong if there are any filters after it. This means that if you write any filters which set the content length, they should do it after the $r->filter_register call.


Add a buffered mode to the final output, so that we can send a proper Content-Length header. [ (Philippe M. Chiasson)]


This uses some funny stuff to figure out when the currently executing handler is the last handler in the chain. As a result, code that manipulates the handler list at runtime (using push_handlers and the like) might produce mayhem. Poke around a bit in the code before you try anything. Let me know if you have a better idea.

As of 0.07, Apache::Filter will automatically return DECLINED when $r->filename points to a directory. This is just because in most cases this is what you want to do (so that mod_dir can take care of the request), and because figuring out the ``right'' way to handle directories seems pretty tough - the right way would allow a directory indexing handler to be a filter, which isn't possible now. Also, you can't properly pass control to a non-mod_perl indexer like mod_autoindex. Suggestions are welcome.

I haven't considered what will happen if you use this and you haven't turned on PERL_STACKED_HANDLERS. So don't do it.


Ken Williams (


Copyright 1998,1999,2000 Ken Williams. All rights reserved.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.