Here's a quick hack that exposes a PerlFilter per-server command that
ap_register_output_filter()s whatever name(s) are provided them with a
cobbled-together modperl_perl_filter_handler().

I can now enable a Perl filter using SetOutputFilter or in a
PerlFixupHandler (in lieue of a PerlFilterRegisterHandler) using
$r->add_output_filter() and things work "noicly":

   PerlSwitches -MApache2::TestOutputFitler
   PerlFilter Apache2::TestOutputFilter

   <LocationMatch /ftest/.*>
       SetOutputFilter Apache2::TestOutputFilter
   </LocationMatch>

or

   sub fixup_handler {
       my $r = shift ;
       # Note: the C<0> is needed since we're (for now) passing a C-level
       # NULL pointer to be put in the filter's ctx slot (f->ctx).
       $r->add_output_filter( "Apache2::TestOutputFilter", 0 ) ;
   }

Some thoughts:
  - All this is also possible for input filters, but less fun so I
    skipped it, and some naming tweaks would need to take place.
  - The filter names are queued in scgf->PerlFilter so that (someday)
    PerlModule or PerlRequire can glance at the list to see what to
    load.
  - I'm wondering if PerlFilter should be a special case of
    PerlOutputFilter when it's seen at RSRC_CONF scope?
  - An alternative is to just ap_register_xxx_filter() when code is
    loaded (due to PerlSwitch -M or PerlModule/PerlRequire commands),
    based on CODE attrs:

       use base qw(Apache::Fitler);

       sub my_output_filter: AP_FTYPE_CONTENT {
       }

       sub my_input_Filter: mp_input_filter, AP_FTYPE_CONTENT {
       }

    They'd get registered when the CODE attrs get handled by
    Apache::Filter.
  - This could replace current Perl{Input,Output}Filter functionality.
    As far as I can see, the overhead is the creation of a
    modperl_filter_ctx_t and a modperl_handler_t for every filter call.
  - The $r->add_output_filter() functionality is cool. I really, really
    want to use this in a piece of code I'm dieing to work on.
  - It seems like it would be easy to add the ->is_bos and ->is_eos to
    the modperl_filter_ctx_t in this scheme and pass it to handlers as
    a hash.
  - Seems like the current filter code leaks a modperl_filter_t every
    filter call (which gets cleaned up in pool cleanup, but still...) 

Barrie

P.S. This applies on top of the more recent EOS patch, and should apply
without the EOS patch with some fuzz, I think.

--- ../modperl-2.0/./src/modules/perl/modperl_filter.c  Thu May 24 10:55:51 2001
+++ ./src/modules/perl/modperl_filter.c Thu May 24 13:40:11 2001
@@ -372,6 +372,44 @@
     }
 }
 
+apr_status_t modperl_perl_filter_handler(ap_filter_t *f,
+                                         apr_bucket_brigade *bb)
+{
+    request_rec          *r = f->r;
+    modperl_handler_t    *handler ;
+    modperl_filter_ctx_t *ctx ;
+    modperl_filter_t     *filter;
+    int status;
+
+    if (APR_BRIGADE_IS_EOS(bb)) {
+        /* XXX: see about preventing this in the first place */
+        MP_TRACE_f(MP_FUNC, "first bucket is EOS, skipping callback\n");
+        return ap_pass_brigade(f->next, bb);
+    }
+    else {
+        if (!f->ctx) {
+            ctx = (modperl_filter_ctx_t *)apr_pcalloc(r->pool, sizeof(*ctx));
+            f->ctx = ctx ;
+
+            handler = modperl_handler_new(r->pool,f->frec->name);
+            ctx->handler = handler ;
+        }
+
+        filter = modperl_filter_new(f, bb, MP_OUTPUT_FILTER_MODE);
+        status = modperl_run_filter(filter, 0, 0);
+        modperl_output_filter_send_EOS(filter);
+    }
+
+    switch (status) {
+      case OK:
+        return APR_SUCCESS;
+      case DECLINED:
+        return ap_pass_brigade(f->next, bb);
+      default:
+        return status; /*XXX*/
+    }
+}
+
 apr_status_t modperl_input_filter_handler(ap_filter_t *f,
                                           apr_bucket_brigade *bb,
                                           ap_input_mode_t mode,
--- ../modperl-2.0/./src/modules/perl/modperl_filter.h  Tue May 22 11:07:28 2001
+++ ./src/modules/perl/modperl_filter.h Thu May 24 12:18:43 2001
@@ -28,6 +28,10 @@
 int modperl_run_filter(modperl_filter_t *filter, ap_input_mode_t mode,
                        apr_size_t *readbytes);
 
+/* "perl" filters: added by httpd, so no context when handler called */
+apr_status_t modperl_perl_filter_handler(ap_filter_t *f,
+                                           apr_bucket_brigade *bb);
+
 /* output filters */
 apr_status_t modperl_output_filter_handler(ap_filter_t *f,
                                            apr_bucket_brigade *bb);
--- ../modperl-2.0/./src/modules/perl/mod_perl.c        Thu May 10 14:48:01 2001
+++ ./src/modules/perl/mod_perl.c       Thu May 24 11:16:48 2001
@@ -323,6 +323,7 @@
 static const command_rec modperl_cmds[] = {  
     MP_CMD_SRV_ITERATE("PerlSwitches", switches, "Perl Switches"),
     MP_CMD_DIR_ITERATE("PerlOptions", options, "Perl Options"),
+    MP_CMD_SRV_ITERATE("PerlFilter", filters, "Perl Filters (visible to Apache)"),
 #ifdef MP_TRACE
     MP_CMD_SRV_TAKE1("PerlTrace", trace, "Trace level"),
 #endif
--- ../modperl-2.0/./src/modules/perl/modperl_cmd.c     Thu Apr  5 22:18:15 2001
+++ ./src/modules/perl/modperl_cmd.c    Thu May 24 12:19:06 2001
@@ -67,6 +67,19 @@
     return NULL;
 }
 
+MP_CMD_SRV_DECLARE(filters)
+{
+    MP_dSCFG(parms->server);
+    *(const char **)apr_array_push(scfg->PerlFilter) = arg ;
+    /* XXX: Need to allow a cmg arg or CODE attr to specify AP_FTYPE_... */
+    ap_register_output_filter(
+        arg,
+        modperl_perl_filter_handler,
+        AP_FTYPE_CONTENT
+    );
+    return NULL;
+}
+
 #ifdef USE_ITHREADS
 
 #define MP_INTERP_SCOPE_USAGE "PerlInterpScope must be one of "
--- ../modperl-2.0/./src/modules/perl/modperl_cmd.h     Thu Apr  5 22:18:15 2001
+++ ./src/modules/perl/modperl_cmd.h    Thu May 24 11:21:01 2001
@@ -11,6 +11,7 @@
 MP_CMD_SRV_DECLARE(trace);
 MP_CMD_SRV_DECLARE(switches);
 MP_CMD_SRV_DECLARE(options);
+MP_CMD_SRV_DECLARE(filters);
 
 #ifdef USE_ITHREADS
 MP_CMD_SRV_DECLARE(interp_start);
--- ../modperl-2.0/./src/modules/perl/modperl_types.h   Thu May 10 14:48:17 2001
+++ ./src/modules/perl/modperl_types.h  Thu May 24 11:33:33 2001
@@ -112,7 +112,7 @@
 typedef struct {
     MpHV *SetVars;
     MpAV *PassEnv;
-    MpAV *PerlRequire, *PerlModule;
+    MpAV *PerlRequire, *PerlModule, *PerlFilter;
     MpAV *handlers_per_srv[MP_HANDLER_NUM_PER_SRV];
     MpAV *handlers_files[MP_HANDLER_NUM_FILES];
     MpAV *handlers_process[MP_HANDLER_NUM_PROCESS];
--- ../modperl-2.0/./src/modules/perl/modperl_config.c  Thu May 10 14:48:07 2001
+++ ./src/modules/perl/modperl_config.c Thu May 24 11:51:06 2001
@@ -71,6 +71,7 @@
     MpSrvENABLED_On(scfg); /* mod_perl enabled by default */
     MpSrvHOOKS_ALL_On(scfg); /* all hooks enabled by default */
 
+    scfg->PerlFilter = apr_array_make(p, 2, sizeof(char *));
     scfg->argv = apr_array_make(p, 2, sizeof(char *));
 
     modperl_config_srv_argv_push((char *)ap_server_argv0);

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to