libapa...:Filter(3pm)
πΈ Apache2::Filter πΈ β the Perl API for Apache 2.0 Filtering
okay bestie, this is from the libapa...:Filter(3pm) page (User Contributed Perl Documentation, for Apache2::Filter), and it's a whole era. Let's get into it π
β¨ SYNOPSIS β¨
use Apache2::Filter ();
# filter attributes
my $c = $f->c;
my $r = $f->r;
my $frec = $f->frec();
my $next_f = $f->next;
my $ctx = $f->ctx;
$f->ctx($ctx);
# bucket brigade filtering API
$rc = $f->next->get_brigade($bb, $mode, $block, $readbytes);
$rc = $f->next->pass_brigade($bb);
$rc = $f->fflush($bb);
# streaming filtering API
while ($filter->read(my $buffer, $wanted)) {
# transform $buffer here
$filter->print($buffer);
}
if ($f->seen_eos) {
$filter->print("filter signature");
}
# filter manipulations
$r->add_input_filter(\&callback);
$c->add_input_filter(\&callback);
$r->add_output_filter(\&callback);
$c->add_output_filter(\&callback);
$f->remove;
π DESCRIPTION π
Apache2::Filter hands you the Perl API for the Apache 2.0 filtering framework. it's giving gateway to all the filter vibes β¨
and like, before you go feral with it β make sure you actually read "the Filtering tutorial|docs::2.0::user::handlers::filters". it's the lore. required reading, fr fr π
π¦ Common Filter API π¦
these methods? you can call them from any filter handler. every single one. slay.
π c π
grab the current connection object, whether you're in a connection filter or a request filter:
$c = $f->c;
- obj:
$f(Apache2::Filter object) - ret:
$c(Apache2::Connection object) - since: 2.0.00
π ctx π
get / set the filter context data. it's the lil storage pocket your filter carries around π
$ctx = $f->ctx;
$f->ctx($ctx);
- obj:
$f(Apache2::Filter object) - opt arg2:
$ctx( SCALAR ) β next context - ret:
$ctx( SCALAR ) β current context - since: 2.0.00
okay so here's the tea on filter context β a filter context is created before the filter gets called for the very first time, and it's destroyed at the end of the request. and it's preserved between filter invocations of the same request β so if your filter needs to stash data between invocations, that's literally what this is for. the filter context starts out initialized with the undef value.
the ctx method takes a single SCALAR argument, so if you wanna store any other perl data structure in there you gotta use a reference to it. iykyk.
for example, you can store a hash reference:
$f->ctx({ foo => 'bar' });
and then access it:
$foo = $f->ctx->{foo};
pro tip bestie: if you're accessing the context more than once, it's more efficient to copy its value before you use it:
my $ctx = $f->ctx;
$foo = $ctx->{foo};
that's how you dodge redundant method calls π as of this writing $ctx is not a tied variable, so if you modify it you need to store it back at the end:
$f->ctx($ctx);
META: later we might make it a TIEd-variable interface, so it'll be stored automatically.
and besides its main character job of storing context data across multiple filter invocations, this method is also super useful as a flag. for example, here's how to make sure something only happens once during the filter's whole life:
unless ($f->ctx) {
do_something_once();
$f->ctx(1);
}
periodt π
π frec π
get / set the Apache2::FilterRec (filter record) object:
$frec = $f->frec();
- obj:
$f(Apache2::Filter object) - ret:
$frec(Apache2::FilterRec object) - since: 2.0.00
for example you can call $frec->name to get the filter's name. cute, right? πΈ
π next π
returns the Apache2::Filter object of the next filter in the chain β the next one in line, bestie π«Ά
$next_f = $f->next;
- obj:
$f(Apache2::Filter object) β the current filter object - ret:
$next_f(Apache2::Filter object) β the next filter object in chain - since: 2.0.00
since Apache inserts several core filters at the end of each chain, normally this method always returns an object. however β if it's not a mod_perl filter handler, you can only call the following methods on it: get_brigade, pass_brigade, c, r, frec and next. call any other method and the behavior is undefined. don't do it. not worth it π
the next filter can be a mod_perl one or not, and it's super easy to tell which one it is β just call $f->frec->name. vibe check complete β¨
π r π
inside an HTTP request filter, retrieve the current request object:
$r = $f->r;
- obj:
$f(Apache2::Filter object) - ret:
$r(Apache2::RequestRec object) - since: 2.0.00
and heads up: if a sub-request adds filters, then that sub-request object is the one associated with the filter. noted π
π remove π
remove the current filter from the filter chain (for the current request or connection):
$f->remove;
- obj:
$f(Apache2::Filter object) - ret: no return value
- since: 2.0.00
notice: you should either complete the current filter invocation normally (by callingget_brigadeorpass_brigade, depending on the filter kind) or β if nothing was done β returnApache2::Const::DECLINED, and mod_perl will take care of passing the current bucket brigade through unmodified to the next filter in chain. those are your options, bestie. no in-between π
Note: calling remove() on the very top connection filter doesn't affect the filter chain due to a bug in Apache 2.0 (which may be fixed in 2.1). so don't use it with connection filters till it gets fixed in Apache β and then make sure to require the minimum Apache version if you rely on it. fr fr, this one bites people π
remember that if the connection is $c->keepalive and the connection filter is removed, it won't be added again until the connection is closed β which may happen after many HTTP requests. so you may wanna keep the filter in place and just pass the data through unmodified by returning Apache2::Const::DECLINED. and if you need to reset the whole thing or parts of the filter context between requests, use the technique based on $c->keepalives counting. iconic workaround energy π
also: this method works for native Apache (non-mod_perl) filters too. equal opportunity slay π
β¨ Bucket Brigade Filter API β¨
ok so these are the methods literally any filter can call, and they mess with bucket brigades directly. no middleman, no nothing. let's get into it π
π fflush
Flushes a bucket brigade down the filter stack. bye brigade π
$rc = $f->fflush($bb);
- obj:
$f(Apache2::Filter object) β the current filter - arg1:
$bb(Apache2::Brigade object) β the brigade to flush - ret:
$rc(APR::Const status constant) β go peek at thepass_brigade()entry for the deets - excpt:
APR::Errorβ exceptions are thrown only when this function is called in the VOID context. refer to theget_brigade()entry for the full story - since:
2.0.00
fflush is a shortcut method, iykyk. so instead of doing all of this:
my $b = APR::Bucket::flush_create($f->c->bucket_alloc);
$bb->insert_tail($b);
$f->pass_brigade($bb);
you can just write this instead:
$f->fflush($bb);
iconic behaviour tbh π«Ά
π₯ get_brigade
this is the method for bucket brigade input filters. it acquires a bucket brigade from the upstream input filter.
$rc = $next_f->get_brigade($bb, $mode, $block, $readbytes);
$rc = $next_f->get_brigade($bb, $mode, $block);
$rc = $next_f->get_brigade($bb, $mode)
$rc = $next_f->get_brigade($bb);
yeah bestie those last two synopsis lines be missing their semicolons in the original. we keep them exactly as they are. no cap π
- obj:
$next_f(Apache2::Filter object) β the next filter in the filter chain.- inside filter handlers it's usually
$f->next. inside protocol handlers:$c->input_filters.
- inside filter handlers it's usually
- arg1:
$bb(APR::Brigade object) β the original bucket brigade passed toget_brigade(), which must be empty.- inside input filter handlers it's usually the second argument to the filter handler.
- otherwise it should be created:
my $bb = APR::Brigade->new($c->pool, $c->bucket_alloc);
- on return it gets populated with the next bucket brigade. that brigade may contain nothing if there was no more data to read. the return status tells you the outcome.
- opt arg2:
$mode(Apache2::Const :input_mode constant) β the filter mode in which the data should be read.- if you're inside the filter handler, you should normally pass the same mode that was passed to the filter handler (that's the third argument).
- the available modes get presented at the end of this section π
- if the argument
$modeis not passed,Apache2::Const::MODE_READBYTESis used as a default value.
- opt arg3:
$block(APR::Const :read_type constant) β you may ask the reading operation to be blocking:APR::Const::BLOCK_READ, or nonblocking:APR::Const::NONBLOCK_READ.- if you're inside the filter handler, you should normally pass the same blocking mode argument that was passed to the filter handler (the forth argument).
- if the argument
$blockis not passed,APR::Const::BLOCK_READis used as a default value.
- opt arg4:
$readbytes(integer) β how many bytes to read from the next filter.- if you're inside the filter handler, you may want the same number of bytes, as the upstream filter, i.e. the argument that was passed to the filter handler (the fifth argument).
- if the argument
$blockis not passed,8192is used as a default value.
- ret:
$rc(APR::Const status constant)- on success,
APR::Const::SUCCESSis returned and$bbis populated (see the$bbentry). - in case of a failure β¨ a failure code is returned, in which case normally it should be returned to the caller.
- if the bottom-most filter doesn't read from the network, then
Apache2::NOBODY_READis returned (META: need to add this constant). - inside protocol handlers the return code can also be
APR::Const::EOF, which is success as well.
- on success,
- excpt:
APR::Error- you don't have to ask for the return value. if this function is called in the VOID context, e.g.:
$f->next->get_brigade($bb, $mode, $block, $readbytes);
- mod_perl will do the error checking on your behalf, and if the return code is not
APR::Const::SUCCESS, anAPR::Error exceptionwill be thrown. the only time you want to do the error checking yourself, is when return codes besidesAPR::Const::SUCCESSare considered as successful and you want to manage them by yourself.
- since:
2.0.00
π Available input filter modes
these are the optional second argument $mode, bestie:
Apache2::Const::MODE_READBYTESβ the filter should return at most readbytes dataApache2::Const::MODE_GETLINEβ the filter should return at most one line of CRLF data. (if a potential line is too long or no CRLF is found, the filter may return partial data).Apache2::Const::MODE_EATCRLFβ the filter should implicitly eat any CRLF pairs that it sees.Apache2::Const::MODE_SPECULATIVEβ the filter read should be treated as speculative and any returned data should be stored for later retrieval in another mode.Apache2::Const::MODE_EXHAUSTIVEβ the filter read should be exhaustive and read until it can not read any more. use this mode with extreme caution β οΈApache2::Const::MODE_INITβ the filter should initialize the connection if needed, NNTP or FTP over SSL for example.
either compile all these constants with:
use Apache2::Const -compile => qw(:input_mode);
but it's a bit more efficient to compile only those constants that you need. π
πΈ Example
here's a fragment of a filter handler that receives a bucket brigade from the upstream filter:
use Apache2::Filter ();
use APR::Const -compile => qw(SUCCESS);
use Apache2::Const -compile => qw(OK);
sub filter {
my ($f, $bb, $mode, $block, $readbytes) = @_;
my $rc = $f->next->get_brigade($bb, $mode, $block, $readbytes);
return $rc unless $rc == APR::Const::SUCCESS;
# ... process $bb
return Apache2::Const::OK;
}
usually the arguments $mode, $block, $readbytes are the same as passed to the filter itself.
you can see that in case of a failure, the handler returns immediately with that failure code, which gets propagated to the downstream filter.
if you decide not check the return code, you can write it as:
sub filter {
my ($f, $bb, $mode, $block, $readbytes) = @_;
$f->next->get_brigade($bb, $mode, $block, $readbytes);
# ... process $bb
return Apache2::Const::OK;
}
and the error checking will be done on your behalf. so β¨convenientβ¨
you will find many more examples in "the filter handlers|docs::2.0::user::handlers::filters" and "the protocol handlers|docs::2.0::user::handlers::protocols" tutorials.
π€ pass_brigade
this is the method for bucket brigade output filters. it passes the current bucket brigade to the downstream output filter.
$rc = $next_f->pass_brigade($bb);
- obj:
$next_f(Apache2::Filter object) β the next filter in the filter chain.- inside output filter handlers it's usually
$f->next. inside protocol handlers:$c->output_filters.
- inside output filter handlers it's usually
- arg1:
$bb(APR::Brigade object) β the bucket brigade to pass.- inside output filter handlers it's usually the second argument to the filter handler (after potential manipulations).
- ret:
$rc(APR::Const status constant)- on success,
APR::Const::SUCCESSis returned. - in case of a failure β¨ a failure code is returned, in which case normally it should be returned to the caller.
- if the bottom-most filter doesn't write to the network, then
Apache2::NOBODY_WROTEis returned (META: need to add this constant). - also refer to the
get_brigade()entry to see how to avoid checking the errors explicitly.
- on success,
- excpt:
APR::Errorβ exceptions are thrown only when this function is called in the VOID context. refer to theget_brigade()entry for details. - since:
2.0.00
the caller relinquishes ownership of the brigade (i.e. it may get destroyed/overwritten/etc. by the callee). so like, goodbye brigade, she's someone else's problem now π
π¦ Example
here's a fragment of a filter handler that passes a bucket brigade to the downstream filter (after some potential processing of the buckets in the bucket brigade):
use Apache2::Filter ();
use APR::Const -compile => qw(SUCCESS);
use Apache2::Const -compile => qw(OK);
sub filter {
my ($f, $bb) = @_;
# ... process $bb
my $rc = $f->next->pass_brigade($bb);
return $rc unless $rc == APR::Const::SUCCESS;
return Apache2::Const::OK;
}
Streaming Filter API πβ¨
Bestie, these next ones are the moment. Any filter that's vibing with the simplified streaming functionality can call them. Universal access, no gatekeeping π
print π
Sends the contents of $buffer along to the next filter in the chain (via the internal buffer, obvs).
$sent = $f->print($buffer);
obj:$f(anApache2::Filter object)arg1:$buffer(string) β the data you're sending, bestie πret:$sent(integer) β how many characters were sent. Girl, you do not need to check this one, because everything should go through, and if something goes wrong an exception gets thrown. Trust. πexcpt:APR::Errorsince: 2.0.00
Heads up babes: this method should be used only in streaming filters. No exceptions. π«
read π
Reads data from the filter. The way that this one just works?
$read = $f->read($buffer, $wanted);
obj:$f(anApache2::Filter object)arg1:$buffer(SCALAR) β the buffer you're filling. Fr fr, all previous data in it will be lost. Gone. Poof. πopt arg2:$wanted(integer) β how many bytes to attempt to read.- If you don't pass this optional argument, the default
8192gets used. Default behavior, slay.
- If you don't pass this optional argument, the default
ret:$read(integer) β how many bytes were actually read.$buffergets populated with the string that got read. If there was nothing to read, it'll hold an empty string. So empty string = nothing happened, not a crisis π«Ά
excpt:APR::Errorsince: 2.0.00
So it reads at most $wanted characters into $buffer, and the returned $read tells you exactly how many got read β which makes it stupidly easy to drop into a while loop:
while ($filter->read(my $buffer, $wanted)) {
# transform $buffer here
$filter->print($buffer);
}
Now here's the tea π΅: this is a streaming filter method, which means it grabs a single bucket brigade behind the scenes and reads data from all its buckets. So it can only read from one bucket brigade per filter invocation. One. That's the rule, bestie.
And if the EOS bucket gets read? The seen_eos method will return a true value. Foreshadowing β¨
seen_eos π
This method returns a true value when the EOS bucket is seen by the read method. It's giving end-of-story energy.
$ok = $f->seen_eos;
obj:$f(anApache2::Filter object) β the filter to removeret:$ok(boolean) β a true value if EOS has been seen, otherwise a false valuesince: 2.0.00
This one only works in streaming filters that exhaustively $f->read all the incoming data in a while loop, like so:
while ($f->read(my $buffer, $wanted)) {
# do something with $buffer
}
if ($f->seen_eos) {
# do something
}
That technique right there is chef's kiss when a streaming filter wants to append something to the very very end of the data, or do a lil something at the end of the last filter invocation. Once the EOS bucket is read, the filter should expect not to be invoked again. It's retired. Enjoy the retirement π
Now, plot twist: if an input streaming filter doesn't consume all the data in the bucket brigade (or even across several bucket brigades, no shame), it has to generate the EOS event by itself. So when the filter is done, it has to set the EOS flag:
$f->seen_eos(1);
And when the filter handler returns, internally mod_perl will handle creating and sending the EOS bucket to the upstream input filter. It's got you π
A similar logic may apply for output filters. Just saying.
β οΈ In most other cases you shouldn't set this flag. Like, don't. When this flag is prematurely set (before the real EOS bucket has arrived) in the current filter invocation, instead of invoking the filter again, mod_perl will create and send the EOS bucket to the next filter and ignore any other bucket brigades that may have been left to consume. That's a big deal. As mentioned earlier, this special behavior is useful for writing special tests that test abnormal situations β so, tests only. Not for your regular code. Periodt.
Other Filter-related API π¦
Other methods which affect filters, but get called on non-Apache2::Filter objects. Different object, same drama.
add_input_filter π₯
Adds &callback filter handler to the input request filter chain.
$r->add_input_filter(\&callback);
Adds &callback filter handler to the input connection filter chain.
$c->add_input_filter(\&callback);
obj:$c(anApache2::Connection object) or$r(anApache2::RequestRec object)arg1:&callback(CODE ref)ret: no return valuesince: 2.0.00
[META:It seems that you can't add a filter when another filter is called. I've tried to add an output connection filter from the input connection filter when it was called for the first time. It didn't have any affect for the first request (over keepalive connection). The only way I succeeded to do that is from that input connection filter'sfilter_inithandler. In fact it does work if there is any filter additional filter of the same kind configured fromhttpd.confor viafilter_init. It looks like there is a bug in httpd, where it doesn't prepare the chain of 3rd party filter if none were inserted before the first filter was called.]π
add_output_filter π€
Adds &callback filter handler to the output request filter chain.
$r->add_output_filter(\&callback);
Adds &callback filter handler to the output connection filter chain.
$c->add_output_filter(\&callback);
obj:$c(anApache2::Connection object) or$r(anApache2::RequestRec object)arg1:&callback(CODE ref)ret: no return valuesince: 2.0.00
Filter Handler Attributes π
Okay so, packages using filter attributes have to subclass Apache2::Filter. Non-negotiable, bestie:
package MyApache2::FilterCool;
use base qw(Apache2::Filter);
Attributes get parsed during the code compilation, by the function MODIFY_CODE_ATTRIBUTES β which is inherited from the Apache2::Filter package. Family inheritance, love that for us πΈ
FilterRequestHandler ποΈ
The FilterRequestHandler attribute tells mod_perl to insert the filter into an HTTP request filter chain.
For example, to configure an output request filter handler, drop the FilterRequestHandler attribute into the handler subroutine's declaration:
package MyApache2::FilterOutputReq;
sub handler : FilterRequestHandler { ... }
and then add the configuration entry:
PerlOutputFilterHandler MyApache2::FilterOutputReq
This is the default mode, bestie. So if you're writing an HTTP request filter, you don't even have to specify this attribute. It's free. It's automatic. It's lowkey iconic.
The section HTTP Request vs. Connection Filters delves into more details, if you wanna go deeper π
FilterConnectionHandler π
The FilterConnectionHandler attribute tells mod_perl to insert this filter into a connection filter chain.
For example, to configure an output connection filter handler, use the FilterConnectionHandler attribute in the handler subroutine's declaration:
package MyApache2::FilterOutputCon;
sub handler : FilterConnectionHandler { ... }
and add the configuration entry:
PerlOutputFilterHandler MyApache2::FilterOutputCon
The section HTTP Request vs. Connection Filters delves into more details π
FilterInitHandler π±
The attribute FilterInitHandler marks the function as suitable to be used as a filter initialization callback β which gets called immediately after a filter is inserted into the filter chain and before it's actually called. Early bird energy.
sub init : FilterInitHandler {
my $f = shift;
#...
return Apache2::Const::OK;
}
In order to hook this filter callback, the real filter has to assign this callback using the FilterHasInitHandler, which accepts a reference to the callback function. Yes, they're a package deal π
For further discussion and examples, refer to the Filter Initialization Phase tutorial section.
FilterHasInitHandler πͺ
If a filter wants to run an initialization callback, it can register one using the FilterHasInitHandler attribute. Similar to push_handlers, the callback reference is expected β not a callback name. And the callback function you use has to have the FilterInitHandler attribute. For example:
package MyApache2::FilterBar;
use base qw(Apache2::Filter);
sub init : FilterInitHandler { ... }
sub filter : FilterRequestHandler FilterHasInitHandler(\&init) {
my ($f, $bb) = @_;
# ...
return Apache2::Const::OK;
}
For further discussion and examples, refer to the Filter Initialization Phase tutorial section. Go read it, bestie, it's good for you π
Configuration βοΈβ¨
mod_perl 2.0 filters configuration is explained in the filter handlers tutorial. That's the whole vibe check right there.
PerlInputFilterHandler
See PerlInputFilterHandler.
PerlOutputFilterHandler
See PerlOutputFilterHandler.
PerlSetInputFilter
See PerlSetInputFilter.
PerlSetOutputFilter
See PerlSetInputFilter.
Nope, that's not a typo on my part, bestie β it saysPerlSetInputFilterforPerlSetOutputFilterin the original. I'm just the messenger π«
TIE Interface ππͺ’
Apache2::Filter also implements a tied interface, so you can work with the $f object as a hash reference. Fancy.
Real talk though: the TIE interface is mostly unimplemented and might be implemented post 2.0 release. So like, it's giving coming soon π
TIEHANDLE
$ret = TIEHANDLE($stashsv, $sv);
obj:$stashsv(SCALAR)arg1:$sv(SCALAR)ret:$ret(SCALAR)since: subject to change
PRINT
$ret = PRINT(...);
obj:...(XXX)ret:$ret(integer)since: subject to change
See Also ππ
mod_perl 2.0 documentation.
Copyright π
mod_perl 2.0 and its core modules are copyrighted under The Apache Software License, Version 2.0.
Authors ππ«Ά
The mod_perl development team and numerous contributors.
And that's a wrap on the whole page, bestie!! π This part came from perl v5.42.3, dated 2026-08-20, and yeah β the page name really is that truncated lil libapa...:Filter(3pm) situation. Aesthetic? Debatable. Iconic? Absolutely. Go forth and filter, you main character πβ¨π
π¦ where this page comes from
- ubuntu stonking: libapache2-mod-perl2 2.0.13-2build3 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms