diff options
author | Justin Erenkrantz <jerenkrantz@apache.org> | 2002-02-19 05:45:53 +0100 |
---|---|---|
committer | Justin Erenkrantz <jerenkrantz@apache.org> | 2002-02-19 05:45:53 +0100 |
commit | 6700fa91fbdee79d035de8a1ebfb108e7e800637 (patch) | |
tree | 3c8d2b019b306dd8a558b0519525ba7d5f96e533 | |
parent | Roy has a new employer (diff) | |
download | apache2-6700fa91fbdee79d035de8a1ebfb108e7e800637.tar.xz apache2-6700fa91fbdee79d035de8a1ebfb108e7e800637.zip |
Introduce AddOutputFilterByType directive.
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
-rw-r--r-- | CHANGES | 2 | ||||
-rw-r--r-- | include/ap_mmn.h | 3 | ||||
-rw-r--r-- | include/http_core.h | 2 | ||||
-rw-r--r-- | server/core.c | 127 |
4 files changed, 133 insertions, 1 deletions
@@ -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>] diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 57bd4607f4..4a87fe9ced 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -95,12 +95,13 @@ * 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 */ diff --git a/include/http_core.h b/include/http_core.h index d03469647f..219cf6721d 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -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? */ diff --git a/server/core.c b/server/core.c index 0b7a0f975d..dd019be49f 100644 --- a/server/core.c +++ b/server/core.c @@ -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, |