You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@perl.apache.org by Stas Bekman <st...@stason.org> on 2003/04/07 11:08:21 UTC

proposal for filter_init implementation (was: Re: rfc: new filtering APIs)

As we now have most of filtering API completed, it's time to finish off the 
filter_init API. Here is a proposal for filter_init implementation:

Extend the struct modperl_filter_ctx_t, to include:

   int init_done;
   modperl_handle_t *init_handler;

now we can register a new sub-routine to perform init for a given
filter and have a flag to make sure that this is done once.

The only troublesome issue is how to configure the addition of the init
function. We have discussed this earlier and at this moment I'm thinking about 
the following two options:

1) I haven't tried yet, but according to the attributes manpage
it's possible to pass arguments to the attributes. If that works to
add an init handler:

sub my_init {
     my $filter = shift;
     # ...
     return OK;
}

to the existing filter handler:

sub handler : FilterRequestHandler {}

one needs to do:

sub handler : FilterRequestHandler FilterInitHandler('my_init') {}

even if this works, we probably might have issues with resolving 'my_init' and 
anonymous callbacks won't be possible.

2) Another alternative is to change the way PerlInputFilterHandler is
configured and let it be TAKE12 instead of ITERATE and then you can just say:

PerlInputFilterHandler handler [init_handler]

but then filter handlers will differ from other handlers. I don't know
if it's a good thing or not. But it's certainly the simplest solution.



The perl API is easy, just change:

void mpxs_Apache__RequestRec_add_input_filter(pTHX_ request_rec *r,
                                               SV *callback)

to:

void mpxs_Apache__RequestRec_add_input_filter(pTHX_ request_rec *r,
                                               SV *callback, SV *init_callback)



__________________________________________________________________
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


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: proposal for filter_init implementation (was: Re: rfc: new filtering APIs)

Posted by Stas Bekman <st...@stason.org>.
Geoffrey Young wrote:

>> Well, we already agreed over irc that this filter_init is a totally 
>> misleading name/feature. But since we didn't participate in the 
>> design/decision making, we have to eat it and pretend that it tastes 
>> good ;)
> 
> 
> unfortunately, yes.  If I had the time and ability, I'd fix the 
> underlying problem in Apache and submit it as a patch, but there are way 
> too many changes involved for me to get it working the way it probably 
> ought to.

this is something to think about for Apache 2.1, the current 2.0-trunk doesn't 
seem to attract architecture changes.


-- 


__________________________________________________________________
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


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: proposal for filter_init implementation (was: Re: rfc: new filtering APIs)

Posted by Geoffrey Young <ge...@modperlcookbook.org>.

Stas Bekman wrote:
> Geoffrey Young wrote:
> 
>>> I still think that most filters will have no init handler. 
>>
>>
>> I agree.  the unfortunate fact is that most ought to have one - that 
>> they don't really means that people are not handling conditional GETs 
>> properly. in 1.3 this merely meant that server load was increased.  
>> with the new filter mechanism, it more likely will mean that the 
>> server will generate unexpected responses.
> 
> 
> I've started throwing this kind of notes into:
> http://perl.apache.org/docs/2.0/user/handlers/filters.html#Writing_Well_Behaving_Filters 
> 
> or may be:
> http://perl.apache.org/docs/2.0/user/handlers/filters.html#Writing_Efficient_Filters 
> 
> I'll add yours and hopefully you will expand on it to make a proper 
> section some time soon.

yeah, once we have an interface down I'll throw some stuff together.

> 
>> yes, $f->ctx is probably fine for all filters except output filters, 
>> for reasons (I hope) I've shown :)
> 
> 
> Well, we already agreed over irc that this filter_init is a totally 
> misleading name/feature. But since we didn't participate in the 
> design/decision making, we have to eat it and pretend that it tastes 
> good ;)

unfortunately, yes.  If I had the time and ability, I'd fix the underlying 
problem in Apache and submit it as a patch, but there are way too many 
changes involved for me to get it working the way it probably ought to.

--Geoff


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: proposal for filter_init implementation (was: Re: rfc: new filtering APIs)

Posted by Stas Bekman <st...@stason.org>.
Geoffrey Young wrote:

>> I still think that most filters will have no init handler. 
> 
> I agree.  the unfortunate fact is that most ought to have one - that 
> they don't really means that people are not handling conditional GETs 
> properly. in 1.3 this merely meant that server load was increased.  with 
> the new filter mechanism, it more likely will mean that the server will 
> generate unexpected responses.

I've started throwing this kind of notes into:
http://perl.apache.org/docs/2.0/user/handlers/filters.html#Writing_Well_Behaving_Filters
or may be:
http://perl.apache.org/docs/2.0/user/handlers/filters.html#Writing_Efficient_Filters
I'll add yours and hopefully you will expand on it to make a proper section 
some time soon.

> yes, $f->ctx is probably fine for all filters except output filters, for 
> reasons (I hope) I've shown :)

Well, we already agreed over irc that this filter_init is a totally misleading 
name/feature. But since we didn't participate in the design/decision making, 
we have to eat it and pretend that it tastes good ;)

> thanks for working on this, Stas.  you rock :)

;)


__________________________________________________________________
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


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: proposal for filter_init implementation (was: Re: rfc: new filtering APIs)

Posted by Geoffrey Young <ge...@modperlcookbook.org>.
>> cool.  does this mean that the code will be available (somehow) via 
>> $f->ctx?  I think that maybe there might be value in being able to do
>>
>> $f->ctx->{init}->();
>>
>> someday :)
> 
> 
> Why complicating things. If you assign an init sub it's always run once 
> before the filter is invoked for the first time. You don't invoke it by 
> yourself.
> 
> But if you want to, you don't have to use an init mechanism (once it's 
> added and simply do:
> 
> sub my_init {}
> 
> sub my_filter {
>   unless ($f->ctx->{init_done}) {
>       my_init();
>       $f->ctx->{init_done}++;
>   }
> }
> 
> That's exactly why I was asking you, whether we really need the filter 
> init mechanism, since it's so easy to implement it when you need it.

ugh.

you need the filter_init because it runs _before_ the filter is called and 
_before_ the real content handler is called - by the time the filter is 
invoked for the first time it is too late.

let's back up a bit.  the reason filter_init was added was because of issues 
with conditional GET requests - basically default_handler checks 
ap_meets_conditions() and can return NOT_MODIFIED before the filter is run, 
circumventing the intentions of the filter.  see mod_include.c's 
includes_setup function for an example of this.  also see the bug report in

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=9673

so, filter_init was created to give filters a way to insert processing into 
the content generation _before_ any handlers run.  the way I would use this 
in Perl-land would be to set update_mtime() based on the mtime of my Perl 
filter - without the hook, the mtime of my filter will _never_ be added to 
Last-Modified once the client has seen the resource at all, since 
default_handler would prevent my update_mtime() from being called at all.

so, even though the name is filter_init, it's not really about initializing 
the filter.  it's more about inserting filter processing before 
default_handler gets a chance to rule the request.

in reality, this whole thing seems totally broken from an Apache standpoint 
to me - default_handler (nor any other content handler) has no right to 
decide to send NOT_MODIFIED when filters are involved. 
ap_meets_conditions(), etag(), etc should probably be in a filter of their 
own.  but this is how Apache is designed, so I guess we're stuck with it.

> 
> [...]
> 
>>> sub handler : FilterRequestHandler FilterInitHandler('my_init') {}
>>>
>>> even if this works, we probably might have issues with resolving 
>>> 'my_init' and anonymous callbacks won't be possible.
>>
>>
>>
>> well, personally I like this approach the best I think.  at the very 
>> least, we need this (in addition to other approaches) in order to 
>> allow module writers to make init routines mandatory (see below).
> 
> 
> Mandatory? Why in the world do you want to make them mandatory?

I hope the above made it clearer.  basically, if your filter is an output 
filter that alters content based on varying criteria (say, a httpd.conf 
directive that can change) then you need to consider conditional GETs in 
your logic.  now, if your filter has conditional GET logic (as all should 
but most don't :) , then you (as the module writer) will not want its use to 
be optional - if it were optional then users would inadventently misuse the 
module, resulting in improper handling of requests.

so, in cases where filters specify a filter_init function, it is mandatory 
that it runs and should not be user configurable.

if this doesn't make sense, then please just trust me on this.  once the 
filter_init mechanism is complete I'll implement a use of it and all will be 
clear, I promise :)

> 
>> as for anonymous subs, we won't be able to use them now or ever?   I 
>> know there are some incomplete issues with using anonymous subs in 
>> certain areas (such as inlined in httpd.conf) but I was assuming that 
>> they would be non-issues eventually.
> 
> 
> Now with handlers. You can certainly push (once anon handlers are 
> supported)
> 
> $r->add_input_filter(sub {...});

yes, of course.  I do miss being able to do

PerlLogHandler 'sub { warn shift->as_string }'

though :)

> 
> As for attributes I simply don't know how would you go about doing:
> 
> sub handler : FilterRequestHandler FilterInitHandler( sub {...} ) {}
> 
> I'm not sure whether this works:
> 
> $r->add_input_filter(sub FilterInitHandler( sub {...} ) {...} );

ah.

> 
>>> 2) Another alternative is to change the way PerlInputFilterHandler is
>>> configured and let it be TAKE12 instead of ITERATE and then you can 
>>> just say:
>>>
>>> PerlInputFilterHandler handler [init_handler]
>>>
>>> but then filter handlers will differ from other handlers. I don't know
>>> if it's a good thing or not. But it's certainly the simplest solution.
>>
>>
>>
>> I don't think this is bad per se, but it cannot be othe only way.  as 
>> I've said before, the init handler will be an integral part of the 
>> filter itself - in most cases you will not want to separate it from 
>> the module, since you will need it in order for the module to function 
>> properly (think managing conditional GETs).  so, asking module users 
>> to do more than
>>
>> PerlOutputFilterHandler My::Filter
>>
>> seems excessive from an EU standpoint for modules that require the 
>> hook - it should be transparent.  it also suggests that the 
>> [init_handler] is optional where it may not be for a given module.
> 
> 
> I see what you mean. But that depends on whether the attributes approach 
> will really work. I'll give it a try today.

coolio.

> 
> I still think that most filters will have no init handler. 

I agree.  the unfortunate fact is that most ought to have one - that they 
don't really means that people are not handling conditional GETs properly. 
in 1.3 this merely meant that server load was increased.  with the new 
filter mechanism, it more likely will mean that the server will generate 
unexpected responses.

> I haven't 
> seen the promised arguments of why do you think it should be mandatory.

again, if today's explanations don't clear it up, then just trust me.  I'll 
show by example as soon as the interface is complete (it will even be 
perl.com article #3 :)

> 
>> the flip side of this is that if you give the module writer no 
>> interface to filter_init (such as solution #1) then module writers 
>> have no way to make the init routine required.  yucko.
> 
> 
> Eh? But both give you an interface to filter_init, I don't follow you.

well, if you take the mandatory argument for given for the moment, then what 
follows is that modules need the ability to add filter_init transparently - 
it's an integral part of the filter, a required part of the filter logic 
that the filter will not operate correctly without.  so, I think it is 
excessive to ask end users to do

PerlOutputFilterHandler My::Filter My::Filter::init

when the writer of My::Filter considers init() part of the filter itself - 
My::Filter requires a way of registering init() on its own without user 
intervention.

> 
>>> The perl API is easy, just change:
>>>
>>> void mpxs_Apache__RequestRec_add_input_filter(pTHX_ request_rec *r,
>>>                                               SV *callback)
>>>
>>> to:
>>>
>>> void mpxs_Apache__RequestRec_add_input_filter(pTHX_ request_rec *r,
>>>                                               SV *callback, SV 
>>> *init_callback)
>>
>>
>>
>> as an aside, is there any reason you keep using input filters as the 
>> example?  I haven't looked over the input filter design as much as 
>> with output filters, but filter_init was added specifically for 
>> handling conditional GET requests with output filters - I'm not sure 
>> what value there is for input filters, or even if the input filter 
>> Apache mechanism supports it.  but if it does, cool :)
> 
> 
> No special reason at all. It was just copy-n-paste and I guess the 
> editor was showing the input filters at that moment.

:)

> 
> You may want to run filter_init for input filters to initialize the 
> filter, unless you use the technique with $f->ctx, which seems just fine 
> to me.

yes, $f->ctx is probably fine for all filters except output filters, for 
reasons (I hope) I've shown :)

thanks for working on this, Stas.  you rock :)

--Geoff


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: proposal for filter_init implementation (was: Re: rfc: new filtering APIs)

Posted by Stas Bekman <st...@stason.org>.
Geoffrey Young wrote:
> 
> 
> Stas Bekman wrote:
> 
>> As we now have most of filtering API completed, it's time to finish 
>> off the filter_init API. 
> 
> 
> :)
> 
>> Here is a proposal for filter_init implementation:
>>
>> Extend the struct modperl_filter_ctx_t, to include:
>>
>>   int init_done;
>>   modperl_handle_t *init_handler;
>>
>> now we can register a new sub-routine to perform init for a given
>> filter and have a flag to make sure that this is done once.
> 
> 
> cool.  does this mean that the code will be available (somehow) via 
> $f->ctx?  I think that maybe there might be value in being able to do
> 
> $f->ctx->{init}->();
> 
> someday :)

Why complicating things. If you assign an init sub it's always run once before 
the filter is invoked for the first time. You don't invoke it by yourself.

But if you want to, you don't have to use an init mechanism (once it's added 
and simply do:

sub my_init {}

sub my_filter {
   unless ($f->ctx->{init_done}) {
       my_init();
       $f->ctx->{init_done}++;
   }
}

That's exactly why I was asking you, whether we really need the filter init 
mechanism, since it's so easy to implement it when you need it.

[...]
>> sub handler : FilterRequestHandler FilterInitHandler('my_init') {}
>>
>> even if this works, we probably might have issues with resolving 
>> 'my_init' and anonymous callbacks won't be possible.
> 
> 
> well, personally I like this approach the best I think.  at the very 
> least, we need this (in addition to other approaches) in order to allow 
> module writers to make init routines mandatory (see below).

Mandatory? Why in the world do you want to make them mandatory?

> as for anonymous subs, we won't be able to use them now or ever?   I 
> know there are some incomplete issues with using anonymous subs in 
> certain areas (such as inlined in httpd.conf) but I was assuming that 
> they would be non-issues eventually.

Now with handlers. You can certainly push (once anon handlers are supported)

$r->add_input_filter(sub {...});

As for attributes I simply don't know how would you go about doing:

sub handler : FilterRequestHandler FilterInitHandler( sub {...} ) {}

I'm not sure whether this works:

$r->add_input_filter(sub FilterInitHandler( sub {...} ) {...} );

>> 2) Another alternative is to change the way PerlInputFilterHandler is
>> configured and let it be TAKE12 instead of ITERATE and then you can 
>> just say:
>>
>> PerlInputFilterHandler handler [init_handler]
>>
>> but then filter handlers will differ from other handlers. I don't know
>> if it's a good thing or not. But it's certainly the simplest solution.
> 
> 
> I don't think this is bad per se, but it cannot be othe only way.  as 
> I've said before, the init handler will be an integral part of the 
> filter itself - in most cases you will not want to separate it from the 
> module, since you will need it in order for the module to function 
> properly (think managing conditional GETs).  so, asking module users to 
> do more than
> 
> PerlOutputFilterHandler My::Filter
> 
> seems excessive from an EU standpoint for modules that require the hook 
> - it should be transparent.  it also suggests that the [init_handler] is 
> optional where it may not be for a given module.

I see what you mean. But that depends on whether the attributes approach will 
really work. I'll give it a try today.

I still think that most filters will have no init handler. I haven't seen the 
promised arguments of why do you think it should be mandatory.

> the flip side of this is that if you give the module writer no interface 
> to filter_init (such as solution #1) then module writers have no way to 
> make the init routine required.  yucko.

Eh? But both give you an interface to filter_init, I don't follow you.

>> The perl API is easy, just change:
>>
>> void mpxs_Apache__RequestRec_add_input_filter(pTHX_ request_rec *r,
>>                                               SV *callback)
>>
>> to:
>>
>> void mpxs_Apache__RequestRec_add_input_filter(pTHX_ request_rec *r,
>>                                               SV *callback, SV 
>> *init_callback)
> 
> 
> as an aside, is there any reason you keep using input filters as the 
> example?  I haven't looked over the input filter design as much as with 
> output filters, but filter_init was added specifically for handling 
> conditional GET requests with output filters - I'm not sure what value 
> there is for input filters, or even if the input filter Apache mechanism 
> supports it.  but if it does, cool :)

No special reason at all. It was just copy-n-paste and I guess the editor was 
showing the input filters at that moment.

You may want to run filter_init for input filters to initialize the filter, 
unless you use the technique with $f->ctx, which seems just fine to me.

__________________________________________________________________
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


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: proposal for filter_init implementation (was: Re: rfc: new filtering APIs)

Posted by Geoffrey Young <ge...@modperlcookbook.org>.

Stas Bekman wrote:
> As we now have most of filtering API completed, it's time to finish off 
> the filter_init API. 

:)

> Here is a proposal for filter_init implementation:
> 
> Extend the struct modperl_filter_ctx_t, to include:
> 
>   int init_done;
>   modperl_handle_t *init_handler;
> 
> now we can register a new sub-routine to perform init for a given
> filter and have a flag to make sure that this is done once.

cool.  does this mean that the code will be available (somehow) via $f->ctx? 
  I think that maybe there might be value in being able to do

$f->ctx->{init}->();

someday :)

> 
> The only troublesome issue is how to configure the addition of the init
> function. We have discussed this earlier and at this moment I'm thinking 
> about the following two options:
> 
> 1) I haven't tried yet, but according to the attributes manpage
> it's possible to pass arguments to the attributes. If that works to
> add an init handler:
> 
> sub my_init {
>     my $filter = shift;
>     # ...
>     return OK;
> }
> 
> to the existing filter handler:
> 
> sub handler : FilterRequestHandler {}
> 
> one needs to do:
> 
> sub handler : FilterRequestHandler FilterInitHandler('my_init') {}
> 
> even if this works, we probably might have issues with resolving 
> 'my_init' and anonymous callbacks won't be possible.

well, personally I like this approach the best I think.  at the very least, 
we need this (in addition to other approaches) in order to allow module 
writers to make init routines mandatory (see below).

as for anonymous subs, we won't be able to use them now or ever?   I know 
there are some incomplete issues with using anonymous subs in certain areas 
(such as inlined in httpd.conf) but I was assuming that they would be 
non-issues eventually.

> 
> 2) Another alternative is to change the way PerlInputFilterHandler is
> configured and let it be TAKE12 instead of ITERATE and then you can just 
> say:
> 
> PerlInputFilterHandler handler [init_handler]
> 
> but then filter handlers will differ from other handlers. I don't know
> if it's a good thing or not. But it's certainly the simplest solution.

I don't think this is bad per se, but it cannot be othe only way.  as I've 
said before, the init handler will be an integral part of the filter itself 
- in most cases you will not want to separate it from the module, since you 
will need it in order for the module to function properly (think managing 
conditional GETs).  so, asking module users to do more than

PerlOutputFilterHandler My::Filter

seems excessive from an EU standpoint for modules that require the hook - it 
should be transparent.  it also suggests that the [init_handler] is optional 
where it may not be for a given module.

the flip side of this is that if you give the module writer no interface to 
filter_init (such as solution #1) then module writers have no way to make 
the init routine required.  yucko.

> 
> 
> 
> The perl API is easy, just change:
> 
> void mpxs_Apache__RequestRec_add_input_filter(pTHX_ request_rec *r,
>                                               SV *callback)
> 
> to:
> 
> void mpxs_Apache__RequestRec_add_input_filter(pTHX_ request_rec *r,
>                                               SV *callback, SV 
> *init_callback)

as an aside, is there any reason you keep using input filters as the 
example?  I haven't looked over the input filter design as much as with 
output filters, but filter_init was added specifically for handling 
conditional GET requests with output filters - I'm not sure what value there 
is for input filters, or even if the input filter Apache mechanism supports 
it.  but if it does, cool :)

--Geoff


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org