]> granicus.if.org Git - apache/commitdiff
introducing the bucketeer
authorIan Holsman <ianh@apache.org>
Sat, 23 Feb 2002 06:43:25 +0000 (06:43 +0000)
committerIan Holsman <ianh@apache.org>
Sat, 23 Feb 2002 06:43:25 +0000 (06:43 +0000)
it lets you set up boundry test conditions for things like
mod-include
PR:
Obtained from:
Submitted by:
Reviewed by:

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@93546 13f79535-47bb-0310-9956-ffa450edef68

modules/test/config.m4
modules/test/mod_bucketeer.c [new file with mode: 0644]

index 01bc0fa9717191217a07c19b25e1c5aa5db82142..337d09572386b97755a7027a3c8d6c371a91117f 100644 (file)
@@ -5,5 +5,6 @@ APACHE_MODULE(optional_hook_export, example optional hook exporter, , , no)
 APACHE_MODULE(optional_hook_import, example optional hook importer, , , no)
 APACHE_MODULE(optional_fn_import, example optional function importer, , , no)
 APACHE_MODULE(optional_fn_export, example optional function exporter, , , no)
+APACHE_MODULE(bucketeer, buckets manipulation filter, , , no)
 
 APACHE_MODPATH_FINISH
diff --git a/modules/test/mod_bucketeer.c b/modules/test/mod_bucketeer.c
new file mode 100644 (file)
index 0000000..b77c86a
--- /dev/null
@@ -0,0 +1,224 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * Portions of this software are based upon public domain software
+ * (zlib functions gz_open and gzwrite)
+ */
+
+/*
+ * mod_bucketeer.c: split buckets whenever we find a control-char
+ *
+ * Written by Ian Holsman (IanH@apache.org)
+ *
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+#include "apr_strings.h"
+#include "apr_general.h"
+#include "util_filter.h"
+#include "apr_buckets.h"
+#include "http_request.h"
+
+
+static const char bucketeerFilterName[] = "BUCKETEER";
+module AP_MODULE_DECLARE_DATA bucketeer_module;
+
+typedef struct bucketeer_filter_config_t
+{
+    char bucketdelimter;
+    char flushdelimiter;
+
+} bucketeer_filter_config_t;
+
+
+static void *create_bucketeer_server_config(apr_pool_t *p, server_rec *s)
+{
+    bucketeer_filter_config_t *c = apr_pcalloc(p, sizeof *c);
+
+    c->bucketdelimter = 0x02; /* ^B */
+    c->flushdelimiter = 0x06; /* ^F */
+
+    return c;
+}
+
+
+typedef struct bucketeer_ctx_t
+{
+    apr_bucket_brigade *bb;
+} bucketeer_ctx_t;
+
+static apr_status_t bucketeer_out_filter(ap_filter_t *f,
+                                       apr_bucket_brigade *bb)
+{
+    apr_bucket *e;
+    request_rec *r = f->r;
+    bucketeer_ctx_t *ctx = f->ctx;
+   
+    bucketeer_filter_config_t *c = ap_get_module_config(r->server->module_config,
+                                                    &bucketeer_module);
+
+    /* If we don't have a context, we need to ensure that it is okay to send
+     * the deflated content.  If we have a context, that means we've done
+     * this before and we liked it.
+     * This could be not so nice if we always fail.  But, if we succeed,
+     * we're in better shape.
+     */
+    if (!ctx) {  
+        if (strncmp(r->content_type, "text/", 5)) {
+            ap_remove_output_filter(f);
+            return ap_pass_brigade(f->next, bb);
+        }
+
+        /* We're cool with filtering this. */
+        ctx = f->ctx = apr_pcalloc(f->r->pool, sizeof(*ctx));
+        ctx->bb = apr_brigade_create(f->r->pool); 
+    }
+
+    APR_BRIGADE_FOREACH(e, bb) {
+        const char *data;
+        apr_size_t len;
+
+        int done = 0;
+        apr_size_t i;
+        apr_size_t lastpos;
+
+        if (APR_BUCKET_IS_EOS(e)) {
+
+            APR_BUCKET_REMOVE(e);
+            APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
+
+            /* Okay, we've seen the EOS.
+             * Time to pass it along down the chain.
+             */
+            return ap_pass_brigade(f->next, ctx->bb);
+        }
+
+        if (APR_BUCKET_IS_FLUSH(e)) {     
+            /*
+             * Ignore flush buckets for the moment.. 
+             * we decide what to stream
+             */
+            continue;
+        }
+
+        /* read */
+        apr_bucket_read(e, &data, &len, APR_BLOCK_READ);
+        if (len>0) {
+            lastpos=0;
+            for (i=0; i<len;i++) {
+                if ( data[i] == c->flushdelimiter ) {
+                    apr_bucket *p;
+                    if ( i-lastpos>0) {
+                        p = apr_bucket_pool_create(apr_pmemdup( f->r->pool,
+                                                            &data[lastpos],
+                                                            i-lastpos),
+                                                    i-lastpos,
+                                                    f->r->pool);
+                        APR_BRIGADE_INSERT_TAIL(ctx->bb,p);
+                    }
+                    lastpos=i+1;
+
+                    p = apr_bucket_flush_create();
+                    APR_BRIGADE_INSERT_TAIL(ctx->bb,p);
+
+                } 
+                else {
+                    if (data[i] == c->bucketdelimter) {
+                        apr_bucket *p;
+                        if ( i-lastpos>0) {
+                            p = apr_bucket_pool_create(apr_pmemdup( f->r->pool,
+                                                                &data[lastpos],
+                                                                i-lastpos),
+                                                       i-lastpos,
+                                                       f->r->pool);
+
+                            APR_BRIGADE_INSERT_TAIL(ctx->bb,p);
+                        }
+                        lastpos=i+1;
+                    }
+                }
+            }
+            /* XXX: really should append this to the next 'real' bucket */
+            if ( lastpos < i ) {
+                apr_bucket *p;
+                p = apr_bucket_pool_create(apr_pmemdup( f->r->pool,&data[lastpos],i-lastpos),i-lastpos,f->r->pool);
+                lastpos=i;
+                APR_BRIGADE_INSERT_TAIL(ctx->bb,p);
+            }
+        }     
+    }
+
+    return APR_SUCCESS;
+}
+
+static void register_hooks(apr_pool_t * p)
+{
+    ap_register_output_filter(bucketeerFilterName, bucketeer_out_filter,
+                              AP_FTYPE_CONTENT-1);
+}
+
+static const command_rec bucketeer_filter_cmds[] = {
+    {NULL}
+};
+
+module AP_MODULE_DECLARE_DATA bucketeer_module = {
+    STANDARD20_MODULE_STUFF,
+    NULL,
+    NULL,
+    create_bucketeer_server_config,
+    NULL,
+    bucketeer_filter_cmds,
+    register_hooks
+};