httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stas Bekman <s...@stason.org>
Subject Re: rfc: new API to traverse filter chains
Date Fri, 11 Apr 2003 06:16:33 GMT
Any comments?

Stas Bekman wrote:
> in mod_perl 2.0 we register only four filter names (in:out:req:conn) and 
> then we install the actuall perl callbacks using one of these four 
> filter names and storing the actual filter's callback information in 
> f->ctx. If later on we want to do something with an inserted filter we 
> have no API to find it, since it's not identified by name, but the data 
> inside f->ctx. Therefore we need a new API to traverse the filter chain 
> and find what we want using a custom callback.
> 
> Here is the API and implementation that I came up with (it needs the 
> docco and the standard DECLARE stuff, which I ask to disregard for now 
> and concentrate on the API/implementation itself; once it's polished 
> I'll post a complete patch).
> 
> The function that I'm requesting to add is somewhat similar to 
> apr_table_do.
> 
> 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;
> }
> 
> I'm not sure regarding the chain argument. Looking at the util_filter.c, 
> it looks in proto_ and normal chain. Could there be a problem on the 
> caller side?
> Won't it be enough to use one of r->output_filters, c->output_filters, 
> r->input_filters, c->input_filters if all I care is the custom filters?
> 
> Here is an example of usage by mod_perl 2.0. This is an implementation 
> of a function that will remove a filter by its perl handler name, e.g.:
> 
>   $r->remove_output_filter("TestHandler::out_filter");
> 
> there is a wrapper that translates this perl-side call to C's 
> modperl_filter_remove_by_handler_name().
> 
> 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); /* XXX: 
> 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);
>     }
> }
> 
> 
> __________________________________________________________________
> 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


-- 


__________________________________________________________________
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


Mime
View raw message