What I was planning is:
registered request filters can be removed in the response handler:
$r->remove_input_filter( __PACKAGE__ . "::in_filter"); $r->remove_output_filter(__PACKAGE__ . "::out_filter");
registered connection filters can be removed in the process_connection handler:
$c->remove_input_filter( __PACKAGE__ . "::in_filter"); $c->remove_output_filter(__PACKAGE__ . "::out_filter");
In the following patch you can see the preparation for this support, implementatin of only $r->remove_output_filter and a test which exercises it.
This patch applies against the latest mod_perl cvs, and the test should work.dev
Index: src/modules/perl/modperl_filter.c
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_filter.c,v
retrieving revision 1.56
diff -u -r1.56 modperl_filter.c
--- src/modules/perl/modperl_filter.c 14 Mar 2003 05:33:18 -0000 1.56
+++ src/modules/perl/modperl_filter.c 1 Apr 2003 07:46:31 -0000
@@ -794,6 +794,92 @@
(unsigned long)callback);
}+typedef int (ap_filter_chain_traverse_fh_t)(void *data, ap_filter_t *f);
+int ap_filter_chain_traverse(ap_filter_chain_traverse_fh_t *traverse,
+ void *data, ap_filter_t **chain);
+
+int ap_filter_chain_traverse(ap_filter_chain_traverse_fh_t *traverse,
+ void *data, ap_filter_t **chain)
+{
+ int rv = 0;
+ ap_filter_t *curr = *chain;
+
+ while (curr) {
+ if ((rv = (*traverse)(data, curr)) != 0) {
+ return rv;
+ }
+ curr = curr->next;
+ }
+ return rv;
+}
+
+typedef struct {
+ char* filter_name;
+ char* handler_name;
+ ap_filter_t* f;
+} filter_chain_traverse_t;
+
+static int find_filter_by_handler_name(void *data, ap_filter_t *f)
+{
+ apr_pool_t* p = f->r ? f->r->pool : f->c->pool;
+ filter_chain_traverse_t* traverse = (filter_chain_traverse_t*)data;
+ char *normalized_name;
+
+ /* 'name' in frec is always lowercased */
+ normalized_name = apr_pstrdup(p, traverse->filter_name);
+ ap_str_tolower(normalized_name);
+
+ /* skip non-mod_perl filters */
+ if (strNE(f->frec->name, normalized_name)) {
+ return 0;
+ } else {
+ modperl_filter_ctx_t *ctx = f->ctx;
+ if (strEQ(ctx->handler->name, traverse->handler_name)) {
+ traverse->f = f;
+ return 1; /* found what we wanted */
+ }
+ }
+
+ return 0;
+}
+
+/* modperl_filter_remove_by_handler_name(aTHX_ r, c,
+ * MP_OUTPUT_FILTER_MODE,
+ * "MyFilter::output_lc")
+ */
+void modperl_filter_remove_by_handler_name(pTHX_ request_rec *r,
+ conn_rec *c,
+ modperl_filter_mode_e mode,
+ char* handler_name)
+{
+ int rv = 0;
+ apr_pool_t *pool = r ? r->pool : c->pool;
+ ap_filter_t *f;
+ filter_chain_traverse_t *traverse =
+ apr_pcalloc(pool, sizeof(filter_chain_traverse_t*));
+
+ /* XXX: generalize for conn/req in/out */
+ traverse->filter_name = MP_FILTER_REQUEST_OUTPUT_NAME;
+ traverse->handler_name = handler_name;
+
+ rv = ap_filter_chain_traverse(find_filter_by_handler_name, traverse,
+ &r->output_filters); /* generalize */
+ if (rv) {
+ f = traverse->f; /* XXX: validate */
+ MP_TRACE_f(MP_FUNC, "found filter handler %s\n", handler_name);
+ }
+ else {
+ Perl_croak(aTHX_ "unable to find filter handler '%s'\n", handler_name);
+ }
+
+ MP_TRACE_f(MP_FUNC, "removing filter %s\n", handler_name);
+ if (mode == MP_INPUT_FILTER_MODE) {
+ ap_remove_input_filter(f);
+ }
+ else {
+ ap_remove_output_filter(f);
+ }
+} void modperl_brigade_dump(apr_bucket_brigade *bb, FILE *fp)
{
Index: src/modules/perl/modperl_filter.h
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_filter.h,v
retrieving revision 1.21
diff -u -r1.21 modperl_filter.h
--- src/modules/perl/modperl_filter.h 3 Mar 2003 03:39:06 -0000 1.21
+++ src/modules/perl/modperl_filter.h 1 Apr 2003 07:46:31 -0000
@@ -90,5 +90,9 @@
modperl_filter_add_t addfunc,
SV *callback, const char *type);+void modperl_filter_remove_by_handler_name(pTHX_ request_rec *r, + conn_rec *c, + modperl_filter_mode_e mode, + char* handler_name);
#endif /* MODPERL_FILTER_H */ Index: xs/Apache/Filter/Apache__Filter.h =================================================================== RCS file: /home/cvs/modperl-2.0/xs/Apache/Filter/Apache__Filter.h,v retrieving revision 1.26 diff -u -r1.26 Apache__Filter.h --- xs/Apache/Filter/Apache__Filter.h 1 Apr 2003 05:20:50 -0000 1.26 +++ xs/Apache/Filter/Apache__Filter.h 1 Apr 2003 07:46:31 -0000 @@ -185,6 +185,17 @@ }
static MP_INLINE
+void mpxs_Apache__RequestRec_remove_output_filter(pTHX_ request_rec *r,
+ char* handler_name)
+{
+
+ modperl_filter_remove_by_handler_name(aTHX_ r,
+ r->connection,
+ MP_OUTPUT_FILTER_MODE,
+ handler_name);
+}
+
+static MP_INLINE
void mpxs_Apache__Filter_remove(pTHX_ I32 items, SV **MARK, SV **SP)
{
modperl_filter_t *modperl_filter;
@@ -207,3 +218,4 @@
ap_remove_output_filter(f);
}
}
+
Index: xs/maps/modperl_functions.map
===================================================================
RCS file: /home/cvs/modperl-2.0/xs/maps/modperl_functions.map,v
retrieving revision 1.56
diff -u -r1.56 modperl_functions.map
--- xs/maps/modperl_functions.map 1 Apr 2003 05:20:50 -0000 1.56
+++ xs/maps/modperl_functions.map 1 Apr 2003 07:46:31 -0000
@@ -90,6 +90,7 @@
MODULE=Apache::Filter PACKAGE=Apache::RequestRec
mpxs_Apache__RequestRec_add_input_filter
mpxs_Apache__RequestRec_add_output_filter
+ mpxs_Apache__RequestRec_remove_output_filter MODULE=Apache::Filter PACKAGE=Apache::Connection
mpxs_Apache__Connection_add_input_filter
Index: xs/tables/current/ModPerl/FunctionTable.pm
===================================================================
RCS file: /home/cvs/modperl-2.0/xs/tables/current/ModPerl/FunctionTable.pm,v
retrieving revision 1.110
diff -u -r1.110 FunctionTable.pm
--- xs/tables/current/ModPerl/FunctionTable.pm 1 Apr 2003 05:20:50 -0000 1.110
+++ xs/tables/current/ModPerl/FunctionTable.pm 1 Apr 2003 07:46:31 -0000
@@ -353,6 +353,24 @@
},
{
'return_type' => 'void',
+ 'name' => 'mpxs_Apache__RequestRec_remove_output_filter',
+ 'args' => [
+ {
+ 'type' => 'PerlInterpreter *',
+ 'name' => 'perl'
+ },
+ {
+ 'type' => 'request_rec *',
+ 'name' => 'r'
+ },
+ {
+ 'type' => 'char *',
+ 'name' => 'handler_name'
+ },
+ ]
+ },
+ {
+ 'return_type' => 'void',
'name' => 'mpxs_Apache__Connection_add_input_filter',
'args' => [
{--- /dev/null 1970-01-01 10:00:00.000000000 +1000 +++ t/filter/both_str_rec_remove.t 2003-04-01 16:36:55.000000000 +1000 @@ -0,0 +1,17 @@ +use strict; +use warnings FATAL => 'all'; + +use Apache::Test; +use Apache::TestRequest; +use Apache::TestUtil; + +plan tests => 1; + +my $data = join ' ', 'A'..'Z', 0..9; +#my $expected = lc $data; # that's what the input filter does +#$expected =~ s/\s+//g; # that's what the output filter does +my $expected = $data; +my $location = '/TestFilter::both_str_rec_remove'; +my $response = POST_BODY $location, content => $data; +ok t_cmp($expected, $response, "lc input and reverse output filters"); +
--- /dev/null 1970-01-01 10:00:00.000000000 +1000
+++ t/filter/TestFilter/both_str_rec_remove.pm 2003-04-01 16:46:22.000000000 +1000
@@ -0,0 +1,61 @@
+package TestFilter::both_str_rec_remove;
+
+# insert an input filter which lowers the case of the data
+# insert an output filter which strips spaces
+
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Filter ();
+
+use Apache::Const -compile => qw(OK M_POST);
+
+sub header_parser {
+ my $r = shift;
+
+ return Apache::DECLINED;
+}
+
+sub out_filter {
+ my $filter = shift;
+
+ while ($filter->read(my $buffer, 1024)) {
+ $buffer =~ s/\s+//g;
+ $filter->print($buffer);
+ }
+
+ Apache::OK;
+}
+
+sub handler {
+ my $r = shift;
+
+ # test adding by sub's name
+ $r->remove_output_filter(__PACKAGE__ . "::out_filter");
+
+ $r->content_type('text/plain');
+
+ if ($r->method_number == Apache::M_POST) {
+ $r->print(ModPerl::Test::read_post($r));
+ }
+
+ return Apache::OK;
+}
+
+
+
+1;
+__DATA__
+<NoAutoConfig>
+ PerlModule TestFilter::both_str_rec_remove
+ <Location /TestFilter::both_str_rec_remove>
+ SetHandler modperl
+ PerlHeaderParserHandler TestFilter::both_str_rec_remove::header_parser
+ PerlOutputFilterHandler TestFilter::both_str_rec_remove::out_filter
+ PerlResponseHandler TestFilter::both_str_rec_remove
+ </Location>
+</NoAutoConfig>
+
+
+
+
__________________________________________________________________ Stas Bekman JAm_pH ------> Just Another mod_perl Hacker http://stason.org/ mod_perl Guide ---> http://perl.apache.org mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com http://modperlbook.org http://apache.org http://ticketmaster.com
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
