]> granicus.if.org Git - apache/commitdiff
Introduce AddOutputFilterByType directive.
authorJustin Erenkrantz <jerenkrantz@apache.org>
Tue, 19 Feb 2002 04:45:53 +0000 (04:45 +0000)
committerJustin Erenkrantz <jerenkrantz@apache.org>
Tue, 19 Feb 2002 04:45:53 +0000 (04:45 +0000)
AddOutputFilterByType DEFLATE text/html

(I will add docco soon, I promise.  If someone beats me to it, cool...)

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

CHANGES
include/ap_mmn.h
include/http_core.h
server/core.c

diff --git a/CHANGES b/CHANGES
index 7e05c7f321fda426fa201b16fba7003f707ee0b2..ce9ddc4c666bcb395959ed4d1509d146a0a9374c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,7 @@
 Changes with Apache 2.0.33-dev
 
+  *) Introduce AddOutputFilterByType directive.  [Justin Erenkrantz]
+
   *) Fix DEBUG_CGI support in mod_cgi.  PR 9670, 9671.
      [David MacKenzie <djm@pix.net>]
 
index 57bd4607f489c5366042d5a79643d33986c2568c..4a87fe9ced5c223e871c544189b7b5b0b6d9508e 100644 (file)
  * 20020118 (2.0.31-dev) Input filtering split of blocking and mode
  * 20020127 (2.0.31-dev) bump for pre_mpm hook change
  * 20020128 (2.0.31-dev) bump for pre_config hook change
+ * 20020218 (2.0.33-dev) bump for AddOutputFilterByType directive
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503230UL /* "AP20" */
 
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
-#define MODULE_MAGIC_NUMBER_MAJOR 20020128
+#define MODULE_MAGIC_NUMBER_MAJOR 20020218
 #endif
 #define MODULE_MAGIC_NUMBER_MINOR 0                     /* 0...n */
 #define MODULE_MAGIC_NUMBER MODULE_MAGIC_NUMBER_MAJOR  /* backward compat */
index d03469647fbecb932bfad3243483d4664dad6a23..219cf6721d817898786d4de31ea7f44d804e3dea 100644 (file)
@@ -507,6 +507,8 @@ typedef struct {
     const char *input_filters;   /* forced with SetInputFilters */
     int accept_path_info;        /* forced with AcceptPathInfo */
 
+    apr_hash_t *ct_output_filters; /* added with AddOutputFilterByType */
+
     /*
      * What attributes/data should be included in ETag generation?
      */
index 0b7a0f975d43b25d0253068ef8347a3e3d808c26..dd019be49f0af0728405430edcffbc2dca19eda0 100644 (file)
@@ -183,6 +183,57 @@ static void *create_core_dir_config(apr_pool_t *a, char *dir)
     return (void *)conf;
 }
 
+/*
+ * Overlay one hash table of ct_output_filters onto another
+ */
+static void *merge_ct_filters(apr_pool_t *p,
+                              const void *key,
+                              apr_ssize_t klen,
+                              const void *overlay_val,
+                              const void *base_val,
+                              const void *data)
+{
+    ap_filter_rec_t *cur;
+    const ap_filter_rec_t *overlay_info = (const ap_filter_rec_t *)overlay_val;
+    const ap_filter_rec_t *base_info = (const ap_filter_rec_t *)base_val;
+
+    cur = NULL;
+    
+    while (overlay_info) {
+        ap_filter_rec_t *new;
+
+        new = apr_pcalloc(p, sizeof(ap_filter_rec_t));
+        new->name = apr_pstrdup(p, overlay_info->name);
+        new->next = cur;
+        cur = new;
+        overlay_info = overlay_info->next;
+    }
+
+    while (base_info) {
+        ap_filter_rec_t *f;
+        int found = 0;
+
+        /* We can't have dups. */
+        f = cur;
+        while (f) {
+            if (!strcasecmp(base_info->name, f->name)) {
+                found = 1;
+                break;
+            }
+            f = f->next;
+        }
+        if (!found) {
+            f = apr_pcalloc(p, sizeof(ap_filter_rec_t));
+            f->name = apr_pstrdup(p, base_info->name);
+            f->next = cur;
+            cur = f;
+        }
+        base_info = base_info->next;
+    }
+
+    return cur;
+}
+
 static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
 {
     core_dir_config *base = (core_dir_config *)basev;
@@ -344,6 +395,21 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
         conf->input_filters = new->input_filters;
     }
 
+    if (conf->ct_output_filters && new->ct_output_filters) {
+        conf->ct_output_filters = apr_hash_merge(a, 
+                                                 new->ct_output_filters,
+                                                 conf->ct_output_filters,
+                                                 merge_ct_filters,
+                                                 NULL);
+    }
+    else if (new->ct_output_filters) {
+        conf->ct_output_filters = apr_hash_copy(a, new->ct_output_filters);
+    }
+    else if (conf->ct_output_filters) {
+        /* That memcpy above isn't enough. */
+        conf->ct_output_filters = apr_hash_copy(a, base->ct_output_filters);
+    }
+
     /*
      * Now merge the setting of the FileETag directive.
      */
@@ -2359,6 +2425,34 @@ static const char *set_limit_nproc(cmd_parms *cmd, void *conf_,
 }
 #endif
 
+static const char *add_ct_output_filters(cmd_parms *cmd, void *conf_,
+                                         const char *arg, const char *arg2)
+{
+    core_dir_config *conf=conf_;
+    ap_filter_rec_t *old, *new;
+
+    if (!conf->ct_output_filters) {
+        conf->ct_output_filters = apr_hash_make(cmd->pool);
+        old = NULL;
+    }
+    else {
+        old = (ap_filter_rec_t*) apr_hash_get(conf->ct_output_filters, arg2,
+                                              APR_HASH_KEY_STRING);
+    }
+
+    new = apr_pcalloc(cmd->pool, sizeof(ap_filter_rec_t));
+    new->name = apr_pstrdup(cmd->pool, arg);
+
+    /* We found something, so let's append it.  */ 
+    if (old) {
+        new->next = old;
+    }
+
+    apr_hash_set(conf->ct_output_filters, arg2, APR_HASH_KEY_STRING, new);
+    
+    return NULL; 
+}
+
 static apr_status_t writev_it_all(apr_socket_t *s,
                                   struct iovec *vec, int nvec,
                                   apr_size_t len, apr_size_t *nbytes)
@@ -2737,6 +2831,9 @@ AP_INIT_TAKE1("SetOutputFilter", ap_set_string_slot,
 AP_INIT_TAKE1("SetInputFilter", ap_set_string_slot, 
        (void *)APR_XtOffsetOf(core_dir_config, input_filters), OR_FILEINFO,
    "filter (or ; delimited list of filters) to be run on the request body"),
+AP_INIT_ITERATE2("AddOutputFilterByType", add_ct_output_filters,
+       (void *)APR_XtOffsetOf(core_dir_config, ct_output_filters), OR_FILEINFO,
+     "output filter name followed by one or more content-types"),
 
 /*
  * These are default configuration directives that mpms can/should
@@ -2879,6 +2976,35 @@ static int core_override_type(request_rec *r)
     return OK;
 }
 
+static int core_filters_type(request_rec *r)
+{
+    core_dir_config *conf;
+    const char *ctype, *ctypes;
+
+    conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+                                                   &core_module);
+
+    /* We can't do anything with proxy requests or if we don't have a filter
+     * configured. */ 
+    if (r->proxyreq != PROXYREQ_NONE || !conf->ct_output_filters) {
+        return OK;
+    }
+
+    ctypes = r->content_type;
+  
+    /* We must be able to handle decorated content-types.  */
+    while (*ctypes && (ctype = ap_getword(r->pool, &ctypes, ';'))) {
+        ap_filter_rec_t *ct_filter;
+        ct_filter = apr_hash_get(conf->ct_output_filters, ctype,
+                                 APR_HASH_KEY_STRING);
+        while (ct_filter) {
+            ap_add_output_filter(ct_filter->name, NULL, r, r->connection);
+            ct_filter = ct_filter->next;
+        }
+    }
+
+    return OK;
+}
 
 static int default_handler(request_rec *r)
 {
@@ -3738,6 +3864,7 @@ static void register_hooks(apr_pool_t *p)
     /* FIXME: I suspect we can eliminate the need for these do_nothings - Ben */
     ap_hook_type_checker(do_nothing,NULL,NULL,APR_HOOK_REALLY_LAST);
     ap_hook_fixups(core_override_type,NULL,NULL,APR_HOOK_REALLY_FIRST);
+    ap_hook_fixups(core_filters_type,NULL,NULL,APR_HOOK_MIDDLE);
     ap_hook_access_checker(do_nothing,NULL,NULL,APR_HOOK_REALLY_LAST);
     ap_hook_create_request(core_create_req, NULL, NULL, APR_HOOK_MIDDLE);
     APR_OPTIONAL_HOOK(proxy, create_req, core_create_proxy_req, NULL, NULL,