summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorGraham Leggett <minfrin@apache.org>2015-10-06 22:33:03 +0000
committerGraham Leggett <minfrin@apache.org>2015-10-06 22:33:03 +0000
commit2da6c9a57a7473c52d81b87e541228225691db6f (patch)
tree9aab1827521baf55de358244cf616bedd219b03c /server
parentf296d2b85b51618ee76b4dfa96673887c4ab909f (diff)
downloadhttpd-2da6c9a57a7473c52d81b87e541228225691db6f.tar.gz
Add the AsyncFilter directive that allows the asynchronous filter
functionality to be switched off for certain classes of filters. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1707161 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'server')
-rw-r--r--server/core.c45
-rw-r--r--server/request.c9
-rw-r--r--server/util_filter.c8
3 files changed, 58 insertions, 4 deletions
diff --git a/server/core.c b/server/core.c
index de3fa23f91..d340d5e3de 100644
--- a/server/core.c
+++ b/server/core.c
@@ -481,7 +481,8 @@ static void *create_core_server_config(apr_pool_t *a, server_rec *s)
conf->protocols = apr_array_make(a, 5, sizeof(const char *));
conf->protocols_honor_order = -1;
-
+ conf->async_filter = 0;
+
return (void *)conf;
}
@@ -555,12 +556,16 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv)
? virt->merge_trailers
: base->merge_trailers;
- conf->protocols = ((virt->protocols->nelts > 0)?
+ conf->protocols = ((virt->protocols->nelts > 0) ?
virt->protocols : base->protocols);
- conf->protocols_honor_order = ((virt->protocols_honor_order < 0)?
+ conf->protocols_honor_order = ((virt->protocols_honor_order < 0) ?
base->protocols_honor_order :
virt->protocols_honor_order);
-
+ conf->async_filter = ((virt->async_filter_set) ?
+ virt->async_filter :
+ base->async_filter);
+ conf->async_filter_set = base->async_filter_set || virt->async_filter_set;
+
return conf;
}
@@ -3887,6 +3892,34 @@ static const char *set_http_protocol(cmd_parms *cmd, void *dummy,
return NULL;
}
+static const char *set_async_filter(cmd_parms *cmd, void *dummy,
+ const char *arg)
+{
+ core_server_config *conf =
+ ap_get_core_module_config(cmd->server->module_config);
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE);
+
+ if (err) {
+ return err;
+ }
+
+ if (strcasecmp(arg, "network") == 0) {
+ conf->async_filter = AP_FTYPE_NETWORK;
+ }
+ else if (strcasecmp(arg, "connection") == 0) {
+ conf->async_filter = AP_FTYPE_CONNECTION;
+ }
+ else if (strcasecmp(arg, "request") == 0) {
+ conf->async_filter = 0;
+ }
+ else {
+ return "AsyncFilter must be 'network', 'connection' or 'request'";
+ }
+ conf->async_filter_set = 1;
+
+ return NULL;
+}
+
static const char *set_http_method(cmd_parms *cmd, void *conf, const char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
@@ -4502,6 +4535,9 @@ AP_INIT_ITERATE("Protocols", set_protocols, NULL, RSRC_CONF,
AP_INIT_TAKE1("ProtocolsHonorOrder", set_protocols_honor_order, NULL, RSRC_CONF,
"'off' (default) or 'on' to respect given order of protocols, "
"by default the client specified order determines selection"),
+AP_INIT_TAKE1("AsyncFilter", set_async_filter, NULL, RSRC_CONF,
+ "'network', 'connection' (default) or 'request' to limit the "
+ "types of filters that support asynchronous handling"),
{ NULL }
};
@@ -5010,6 +5046,7 @@ static conn_rec *core_create_conn(apr_pool_t *ptrans, server_rec *s,
c->bucket_alloc = alloc;
c->empty = apr_brigade_create(c->pool, c->bucket_alloc);
c->filters = apr_hash_make(c->pool);
+ c->async_filter = sconf->async_filter;
c->clogging_input_filters = 0;
diff --git a/server/request.c b/server/request.c
index 9c9ad9f93b..abf084e31a 100644
--- a/server/request.c
+++ b/server/request.c
@@ -2043,6 +2043,15 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_request_core_filter(ap_filter_t *f,
apr_status_t status = APR_SUCCESS;
apr_bucket_brigade *tmp_bb = f->ctx;
+ /*
+ * Handle the AsyncFilter directive. We limit the filters that are
+ * eligible for asynchronous handling here.
+ */
+ if (f->frec->ftype < f->c->async_filter) {
+ ap_remove_output_filter(f);
+ return ap_pass_brigade(f->next, bb);
+ }
+
if (!tmp_bb) {
tmp_bb = f->ctx = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
}
diff --git a/server/util_filter.c b/server/util_filter.c
index ad14112ddb..949d13e0a8 100644
--- a/server/util_filter.c
+++ b/server/util_filter.c
@@ -894,6 +894,14 @@ AP_DECLARE(apr_status_t) ap_filter_reinstate_brigade(ap_filter_t *f,
AP_DECLARE(int) ap_filter_should_yield(ap_filter_t *f)
{
/*
+ * Handle the AsyncFilter directive. We limit the filters that are
+ * eligible for asynchronous handling here.
+ */
+ if (f->frec->ftype < f->c->async_filter) {
+ return 0;
+ }
+
+ /*
* This function decides whether a filter should yield due to buffered
* data in a downstream filter. If a downstream filter buffers we
* must back off so we don't overwhelm the server. If this function