You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Torsten Förtsch <to...@gmx.net> on 2004/10/21 21:21:54 UTC

[mp2] $filter->remove patch

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,

the attached patch makes Apache::Filter::remove work also for nativ filters.

Why do I need this?

First, from a users point of view it is not very understandable why a mod_perl 
filter can be removed but a native filter (eg. INCLUDES) cannot.

My actual problem is the following. I have got some CGI and mod_perl scripts 
that generate HTML and images. The HTML output should be filtered by INCLUDES 
and a mod_perl filter, the images should be filtered only by my mod_perl 
filter. The mod_perl filter must be called _after_ INCLUDES.

If I "AddOutputFilterByType INCLUDES text/html" the INCLUDES filter is called 
_before_ the mod_perl filter. If I use PerlSetOutputFilter the filters are 
called in the right order but INCLUDES is called for all documents.

There are multiple solutions. I could patch mod_include or add a 
PerlAddOutputFilterByType directive or just use the existing 
PerlSetOutputFilter and write a little filter that checks the requests 
content-type and removes the next filter in the chain if needed:

PerlOutputFilterHandler Apache::Opis::RemoveNextFilterIfNotTextHtml
PerlSetOutputFilter INCLUDES
PerlOutputFilterHandler Apache::Opis::MyFilter

where Apache::Opis::MyFilter is the filter that needs to be called after 
INCLUDES. The removing filter looks like:

- --------------------------------------------------------------------
package Apache::Opis::RemoveNextFilterIfNotTextHtml;

use strict;
use Apache::Filter ();
use Apache::FilterRec ();
use Apache::RequestRec ();

use Apache::Const -compile => qw(OK DECLINED);

sub handler {
  my $f   = shift;
  my $r   = $f->r;

  unless( $r->content_type =~ m!text/html!i ) {
    eval {
      $f->next->remove;
    };
    warn $@ if $@;
  }
  $f->remove;

  return Apache::DECLINED;
}

1;
- --------------------------------------------------------------------

This code fails with INCLUDES because mod_include is not a mod_perl filter. 
Hence I had to patch Apache::Filter::remove.

Torsten


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)

iD8DBQFBeAxWwicyCTir8T4RAnqyAJ0UW7ky8Z4ApZND9SDpX+LMNzijuACfZwkM
fQvJW0WchvJo9MsUvJmCoos=
=mizK
-----END PGP SIGNATURE-----

Re: [mp2] $filter->remove patch

Posted by Stas Bekman <st...@stason.org>.
Torsten Förtsch wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> On Friday 22 October 2004 19:10, Stas Bekman wrote:
> 
>>>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?
> 
> 
> Yes, I agree that there will be much more output filters but since we cannot 
> not determine if ap_remove_output_filter has actually removed the filter we 
> have to call ap_remove_input_filter in any case. Hence the calling order is 
> all the same.

Hmm, haven't thought of that :)

Thanks again

-- 
__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org 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


Re: [mp2] $filter->remove patch

Posted by Torsten Förtsch <to...@gmx.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Friday 22 October 2004 19:10, Stas Bekman wrote:
> > 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?

Yes, I agree that there will be much more output filters but since we cannot 
not determine if ap_remove_output_filter has actually removed the filter we 
have to call ap_remove_input_filter in any case. Hence the calling order is 
all the same.

> > 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)

Looks good to me

> I'll commit it as soon as Philippe releases 1.99_17 (today?)

Thanks

Torsten
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)

iD8DBQFBeVL0wicyCTir8T4RAiCiAKCT1gXWqPle5r08q7BSSFEhYKvr7QCdGedI
Nszf0Y4AANkitUcjzn2CeDM=
=iQl2
-----END PGP SIGNATURE-----

-- 
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


Re: [mp2] $filter->remove patch

Posted by Stas Bekman <st...@stason.org>.
Stas Bekman wrote:
[...]
>> 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?)

Now committed. Thanks Torsten.

-- 
__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org 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


Re: [mp2] $filter->remove patch

Posted by Stas Bekman <st...@stason.org>.
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:stas@stason.org 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


Re: [mp2] $filter->remove patch

Posted by Torsten Förtsch <to...@gmx.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Friday 22 October 2004 00:38, Stas Bekman wrote:
> Torsten F�rtsch wrote:
> > + � �if( f->c ) {
> > +�����for( list=f->c->input_filters; list; list=list->next ) {
> > +����� � �if( list==f ) {
> > +�������������ap_remove_input_filter(f);
> > +�������������return;
> > +����� � �}
> > +�����}
> > + � �}
>
> [ snipped other filter chains traversals ]
>
> 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.

> > +static MP_INLINE
> > �void mpxs_Apache__Filter_remove(pTHX_ I32 items, SV **MARK, SV **SP)
> > �{
> > � � �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);
> > +
> > + � �if( !modperl_filter ) {��/* native filter */
> > + � � � �mpxs_Apache__Filter_remove_native_filter(aTHX_
> > (ap_filter_t*)SvIV(SvRV(*MARK))); +�����return;
> > + � �}
> > +
> > � � �f = modperl_filter->f;
> > �
> > � � �MP_TRACE_f(MP_FUNC, " � %s\n\n\tfilter removes itself\n",
>
> Also if you could add a test, that will save some time to us. e.g. take
> the t/filter/TestFilter/both_str_req_mix.pm as the base (could probably
> simplify it a bit to just test that it can be removed both on input and
> output). to make your work easier you could just start messing with this
> test and then post it or if you know A-T better you could start a new test

The attached patch contains the updated Apache__Filter.h and a test that 
removes INCLUDES from the output chain and DEFLATE from input.

Torsten
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)

iD8DBQFBeQbrwicyCTir8T4RAtq3AJ9Gpdal0wooCpAST5MYY92dJmueLwCfffB8
KnDaSw1Xs7JDLBQNICt0b5Y=
=YYFu
-----END PGP SIGNATURE-----

Re: [mp2] $filter->remove patch

Posted by Stas Bekman <st...@stason.org>.
Torsten Förtsch wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Hi,
> 
> the attached patch makes Apache::Filter::remove work also for nativ filters.
> 
> Why do I need this?

[explanation snipped]

I see no reason why we shouldn't support that.

> --- mod_perl-1.99_16/xs/Apache/Filter/Apache__Filter.h~	2004-07-12 09:32:07.000000000 +0200
> +++ mod_perl-1.99_16/xs/Apache/Filter/Apache__Filter.h	2004-10-21 13:52:13.243774248 +0200
> @@ -277,12 +277,85 @@
>  }
>  
>  static MP_INLINE
> +void mpxs_Apache__Filter_remove_native_filter(pTHX_ ap_filter_t* f)
> +{
> +    ap_filter_t *list;
> +
> +    if( f->c ) {
> +	for( list=f->c->input_filters; list; list=list->next ) {
> +	    if( list==f ) {
> +		ap_remove_input_filter(f);
> +		return;
> +	    }
> +	}
> +    }

[ snipped other filter chains traversals ]

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?

> +static MP_INLINE
>  void mpxs_Apache__Filter_remove(pTHX_ I32 items, SV **MARK, SV **SP)
>  {
>      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);
> +
> +    if( !modperl_filter ) {	/* native filter */
> +        mpxs_Apache__Filter_remove_native_filter(aTHX_ (ap_filter_t*)SvIV(SvRV(*MARK)));
> +	return;
> +    }
> +
>      f = modperl_filter->f;
>  
>      MP_TRACE_f(MP_FUNC, "   %s\n\n\tfilter removes itself\n",

Also if you could add a test, that will save some time to us. e.g. take 
the t/filter/TestFilter/both_str_req_mix.pm as the base (could probably 
simplify it a bit to just test that it can be removed both on input and 
output). to make your work easier you could just start messing with this 
test and then post it or if you know A-T better you could start a new test


-- 
__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org 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