From: Stefan Eissing Date: Thu, 13 Aug 2015 15:33:07 +0000 (+0000) Subject: new directive ProtocolsHonorOrder, added documentation for Protocols feature, changed... X-Git-Tag: 2.5.0-alpha~2967 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=58119ed85c9f61ae22e1b023d68456e4f4c1d258;p=thirdparty%2Fapache%2Fhttpd.git new directive ProtocolsHonorOrder, added documentation for Protocols feature, changed preference selection and config merging git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1695727 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/docs/manual/mod/core.xml b/docs/manual/mod/core.xml index e9f0596a4b6..f3eb55ce79b 100644 --- a/docs/manual/mod/core.xml +++ b/docs/manual/mod/core.xml @@ -3710,6 +3710,71 @@ Protocol https + + Protocols + Protocols available for a server/virtual host + Protocols protocol ... + server configvirtual host + Only available from Apache 2.4.17 and later. + + +

This directive specifies the list of protocols supported for a + server/virtual host. The list determines the allowed protocols + a client may negotiate for this server/host.

+ +

You only need to set protocols if you want to limit the available + protocols for a server/host. By default, all supported protocols + are available to a client.

+ +

For example, if you want to support only HTTP/1.1 for a server, even + though HTTP/2 is available, just specify this protocol only:

+ + + Protocols http/1.1 + + +

Valid protocols are http/1.1 for http and https connections, + h2 on https connections and h2c for http + connections. Modules may enable more protocols.

+ +

It is safe to specify protocols that are unavailable/disabled. Such + protocol names will simply be ignored.

+ +

Protocols specified in base servers and virtual hosts are concatenated + by appending the base ones, if there are configured protocols, + to the virtual host ones. Since protocols such as HTTP/2 allow + connection reuse under certain conditions, restricting protocols for + individual virtual hosts might not work as you expect it to.

+ +
+ ProtocolsHonorOrder +
+ + + + ProtocolsHonorOrder + Protocols available for a server/virtual host + ProtocolsHonorOrder On|Off + ProtocolsHonorOrder Off + server configvirtual host + Only available from Apache 2.4.17 and later. + + +

This directive specifies if the server should honor the order in which + the Protocols directive lists protocols.

+ +

By default, a client supplies a list of supported protocols and the server + selects an available one from that list in the given order.

+ +

With ProtocolsHonorOrder set to on, the + client ordering does not matter and only the ordering in the server + settings influences the outcome of the protocol negotiation.

+ +
+ Protocols +
+ + RLimitCPU Limits the CPU consumption of processes launched diff --git a/include/http_core.h b/include/http_core.h index 0b19deedd4e..13196e1059d 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -710,6 +710,7 @@ typedef struct { apr_array_header_t *protocols; + int protocols_honor_order; } core_server_config; /* for AddOutputFiltersByType in core.c */ diff --git a/server/core.c b/server/core.c index 97c0b1c862f..e7383970a77 100644 --- a/server/core.c +++ b/server/core.c @@ -479,6 +479,7 @@ static void *create_core_server_config(apr_pool_t *a, server_rec *s) conf->trace_enable = AP_TRACE_UNSET; conf->protocols = apr_array_make(a, 5, sizeof(const char *)); + conf->protocols_honor_order = -1; return (void *)conf; } @@ -553,8 +554,11 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv) ? virt->merge_trailers : base->merge_trailers; - conf->protocols = apr_array_append(p, base->protocols, virt->protocols); - + conf->protocols = apr_array_append(p, virt->protocols, base->protocols); + conf->protocols_honor_order = ((virt->protocols_honor_order < 0)? + base->protocols_honor_order : + virt->protocols_honor_order); + return conf; } @@ -3815,13 +3819,36 @@ static const char *set_protocols(cmd_parms *cmd, void *dummy, return err; } - /* Should we check for some ALPN valid char sequence here? */ np = (const char **)apr_array_push(conf->protocols); *np = arg; return NULL; } +static const char *set_protocols_honor_order(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, "on") == 0) { + conf->protocols_honor_order = 1; + } + else if (strcasecmp(arg, "off") == 0) { + conf->protocols_honor_order = 0; + } + else { + return "ProtocolsHonorOrder must be 'on' or 'off'"; + } + + return NULL; +} + static const char *set_http_protocol(cmd_parms *cmd, void *dummy, const char *arg) { @@ -4469,7 +4496,10 @@ AP_INIT_FLAG("HttpContentLengthHeadZero", set_cl_head_zero, NULL, OR_OPTIONS, AP_INIT_FLAG("HttpExpectStrict", set_expect_strict, NULL, OR_OPTIONS, "whether to return a 417 if a client doesn't send 100-Continue"), AP_INIT_ITERATE("Protocols", set_protocols, NULL, RSRC_CONF, - "Controls which protocols are allowed, sorted by preference"), + "Controls which protocols are allowed"), +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"), { NULL } }; diff --git a/server/protocol.c b/server/protocol.c index bf1dc518cfa..4577d23383e 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -2006,6 +2006,9 @@ AP_DECLARE(const char *) ap_select_protocol(conn_rec *c, request_rec *r, if (proposals->nelts > 0) { int i; + apr_array_header_t *prefs = ((conf->protocols_honor_order > 0 + && conf->protocols->nelts > 0)? + conf->protocols : choices); /* Select the most preferred protocol */ if (APLOGcdebug(c)) { ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, @@ -2020,7 +2023,7 @@ AP_DECLARE(const char *) ap_select_protocol(conn_rec *c, request_rec *r, continue; } else if (!protocol - || (protocol_cmp(conf->protocols, protocol, p) < 0)) { + || (protocol_cmp(prefs, protocol, p) < 0)) { /* none selected yet or this on has preference */ protocol = p; }