Torsten Förtsch wrote:
but why do you need to traverse all these lists? is it because we don't know whether the given filter is an input filter or output one? May be it's easier to attach some flag to the filter object to say which kind of filter is that?
I thought about it this night and realized that I need not to traverse these lists at all. At first ist was a try to guess what to call ap_input_filter_remove or ap_output_filter_remove. But if the filter is not in an appropriate chain these functions do simply nothing. Hence I can call them both if I don't know what kind of filter it is.
I wish we could somehow know what kind of filter is in question. In which case we won't have needed to run wasteful CPU cycles. BTW, I've reversed the order of removal, since I believe we will have many more output filters than input ones. What do you think?
The attached patch contains the updated Apache__Filter.h and a test that removes INCLUDES from the output chain and DEFLATE from input.
Excellent. I've massaged both quite a bit to adher to the style and simplify where it made sense (And found a perl bug in regex qr//m on the way :( see my latest report to p5p)
I'll commit it as soon as Philippe releases 1.99_17 (today?)
Index: Changes =================================================================== RCS file: /home/cvs/modperl-2.0/Changes,v retrieving revision 1.513 diff -u -u -r1.513 Changes --- Changes 15 Oct 2004 19:26:06 -0000 1.513 +++ Changes 22 Oct 2004 17:07:51 -0000 @@ -12,6 +12,9 @@
=item 1.99_17-dev
+$filter->remove now works with native (non-modperl) filters + test +[Torsten Förtsch <torsten.foertsch gmx.net>] + fix xs_generate to croak on duplicate entries in xs/maps files [Christian Krause <chkr plauener.de>]
Index: xs/Apache/Filter/Apache__Filter.h =================================================================== RCS file: /home/cvs/modperl-2.0/xs/Apache/Filter/Apache__Filter.h,v retrieving revision 1.42 diff -u -u -r1.42 Apache__Filter.h --- xs/Apache/Filter/Apache__Filter.h 1 Oct 2004 03:30:12 -0000 1.42 +++ xs/Apache/Filter/Apache__Filter.h 22 Oct 2004 17:07:54 -0000 @@ -284,7 +284,28 @@ modperl_filter_t *modperl_filter; ap_filter_t *f;
- mpxs_usage_va_1(modperl_filter, "$filter->remove()"); + if (items < 1) { + Perl_croak(aTHX_ "usage: $filter->remove()"); + } + + modperl_filter = mp_xs_sv2_modperl_filter(*MARK); + + /* native filter */ + if (!modperl_filter) { + f = (ap_filter_t*)SvIV(SvRV(*MARK)); + MP_TRACE_f(MP_FUNC, + " %s\n\n\t non-modperl filter removes itself\n", + f->frec->name); + + /* the filter can reside in only one chain. hence we try to + * remove it first from the output chains (more likely to be + * the one) then from the input chains. + */ + ap_remove_output_filter(f); + ap_remove_input_filter(f); + return; + } + f = modperl_filter->f;
MP_TRACE_f(MP_FUNC, " %s\n\n\tfilter removes itself\n",
--- /dev/null 1969-12-31 19:00:00.000000000 -0500 +++ t/filter/both_str_native_remove.t 2004-10-22 12:43:40.071433961 -0400 @@ -0,0 +1,59 @@ +use strict; +use warnings FATAL => 'all'; + +use Apache::Test; +use Apache::TestRequest; +use Apache::TestUtil; + +plan tests => 8, need 'deflate', 'include', + need_min_module_version("Compress::Zlib", "1.09"); + +require Compress::Zlib; + +my $base = '/TestFilter__both_str_native_remove'; + +# 1. check if DEFLATE input and INCLUDES output filter work +{ + my $location = $base; + my $received = POST_BODY $location, + content => Compress::Zlib::memGzip('gzipped text'), + 'Content-Encoding' => "gzip"; + + ok t_cmp $received, qr/xSSI OK/, "INCLUDES filter"; + + ok t_cmp $received, qr/content: gzipped text/, "DEFLATE filter"; +} + + +# 2. check if DEFLATE input and INCLUDES output filter can be removed +{ + my $location = "$base?remove"; + my $received = POST_BODY $location, content => 'plain text'; + + ok t_cmp $received, + qr/input1: [\w,]+deflate/, + "DEFLATE filter is present"; + + ok !t_cmp $received, + qr/input2: [\w,]+deflate/, + "DEFLATE filter is removed"; + + ok t_cmp $received, + qr/content: plain text/, + "DEFLATE filter wasn't invoked"; + + ok t_cmp $received, + qr/output1: modperl_request_output,includes,modperl_request_output,/, + "INCLUDES filter is present"; + + ok t_cmp $received, + qr/output2: modperl_request_output,(?!includes)/, + "INCLUDES filter is removed"; + + ok t_cmp $received, + qr/x<!--#echo var="SSI_TEST" -->x/, + "INCLUDES filter wasn't invoked"; + +} + +
--- /dev/null 1969-12-31 19:00:00.000000000 -0500
+++ t/filter/TestFilter/both_str_native_remove.pm 2004-10-22 13:02:11.096991308 -0400
@@ -0,0 +1,137 @@
+package TestFilter::both_str_native_remove;
+
+# this tests verifies that we can remove input and output native
+# (non-mod_perl filters)
+
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::RequestRec ();
+use Apache::RequestIO ();
+
+use Apache::Filter ();
+use Apache::FilterRec ();
+
+use Apache::Const -compile => qw(OK DECLINED);
+
+# this filter removes the next filter in chain and itself
+sub remove_includes {
+ my $f = shift;
+
+ my $args = $f->r->args || '';
+ if ($args eq 'remove') {
+ my $ff = $f->next;
+ $ff->remove if $ff && $ff->frec->name eq 'includes';
+ }
+
+ $f->remove;
+
+ return Apache::DECLINED;
+}
+
+# this filter removes the next filter in chain and itself
+sub remove_deflate {
+ my $f = shift;
+
+ my $args = $f->r->args || '';
+ if ($args eq 'remove') {
+ for (my $ff = $f->r->input_filters; $ff; $ff = $ff->next) {
+ if ($ff->frec->name eq 'deflate') {
+ $ff->remove;
+ last;
+ }
+ }
+ }
+ $f->remove;
+
+ return Apache::DECLINED;
+}
+
+# this filter appends the output filter list at eos
+sub print_out_flist {
+ my $f = shift;
+
+ unless ($f->ctx) {
+ $f->ctx(1);
+ $f->r->headers_out->unset('Content-Length');
+ }
+
+ while ($f->read(my $buffer, 1024)) {
+ $f->print($buffer);
+ }
+
+ if ($f->seen_eos) {
+ my $flist = join ',', get_flist($f->r->output_filters);
+ $f->print("output2: $flist\n");
+ }
+
+ return Apache::OK;
+}
+
+sub store_in_flist {
+ my $f = shift;
+ my $r = $f->r;
+
+ unless ($f->ctx) {
+ my $x = $r->pnotes('INPUT_FILTERS') || [];
+ push @$x, join ',', get_flist($f->r->input_filters);
+ $r->pnotes('INPUT_FILTERS' => $x);
+ }
+
+ return Apache::DECLINED;
+}
+
+
+sub response {
+ my $r = shift;
+
+ # just to make sure that print() won't flush, or we would get the
+ # count wrong
+ local $| = 0;
+
+ $r->content_type('text/plain');
+ if ($r->method_number == Apache::M_POST) {
+ $r->print("content: " . ModPerl::Test::read_post($r) ."\n");
+ }
+
+ my $i=1;
+ for (@{ $r->pnotes('INPUT_FILTERS')||[] }) {
+ $r->print("input$i: $_\n");
+ $i++;
+ }
+
+ $r->subprocess_env(SSI_TEST => 'SSI OK');
+ $r->printf("output1: %s\n", join ',', get_flist($r->output_filters));
+
+ $r->rflush; # this sends the data in the buffer + flush bucket
+ $r->print('x<!--#echo var=');
+ $r->rflush; # this sends the data in the buffer + flush bucket
+ $r->print('"SSI_TEST" -->x'."\n");
+
+ Apache::OK;
+}
+
+sub get_flist {
+ my $f = shift;
+
+ my @flist = ();
+ for (; $f; $f = $f->next) {
+ push @flist, $f->frec->name;
+ }
+
+ return @flist;
+}
+
+1;
+__DATA__
+Options +Includes
+SetHandler modperl
+PerlModule TestFilter::both_str_native_remove
+PerlResponseHandler TestFilter::both_str_native_remove::response
+PerlOutputFilterHandler TestFilter::both_str_native_remove::remove_includes
+PerlSetOutputFilter INCLUDES
+PerlOutputFilterHandler TestFilter::both_str_native_remove::print_out_flist
+PerlInputFilterHandler TestFilter::both_str_native_remove::store_in_flist
+PerlInputFilterHandler TestFilter::both_str_native_remove::remove_deflate
+PerlSetInputFilter DEFLATE
+PerlInputFilterHandler TestFilter::both_str_native_remove::store_in_flist
-- __________________________________________________________________ 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
-- Report problems: http://perl.apache.org/bugs/ Mail list info: http://perl.apache.org/maillist/modperl.html List etiquette: http://perl.apache.org/maillist/email-etiquette.html