summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustin Erenkrantz <jerenkrantz@apache.org>2002-02-19 05:45:53 +0100
committerJustin Erenkrantz <jerenkrantz@apache.org>2002-02-19 05:45:53 +0100
commit6700fa91fbdee79d035de8a1ebfb108e7e800637 (patch)
tree3c8d2b019b306dd8a558b0519525ba7d5f96e533
parentRoy has a new employer (diff)
downloadapache2-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--CHANGES2
-rw-r--r--include/ap_mmn.h3
-rw-r--r--include/http_core.h2
-rw-r--r--server/core.c127
4 files changed, 133 insertions, 1 deletions
diff --git a/CHANGES b/CHANGES
index 7e05c7f321..ce9ddc4c66 100644
--- 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>]
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,