</directivesynopsis>
+<directivesynopsis>
+ <name>Protocols</name>
+ <description>Protocols available for a server/virtual host</description>
+ <syntax>Protocols <var>protocol</var> ...</syntax>
+ <contextlist><context>server config</context><context>virtual host</context></contextlist>
+ <compatibility>Only available from Apache 2.4.17 and later.</compatibility>
+
+ <usage>
+ <p>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.</p>
+
+ <p>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.</p>
+
+ <p>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:</p>
+
+ <highlight language="config">
+ Protocols http/1.1
+ </highlight>
+
+ <p>Valid protocols are <code>http/1.1</code> for http and https connections,
+ <code>h2</code> on https connections and <code>h2c</code> for http
+ connections. Modules may enable more protocols.</p>
+
+ <p>It is safe to specify protocols that are unavailable/disabled. Such
+ protocol names will simply be ignored.</p>
+
+ <p>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.</p>
+
+ </usage>
+ <seealso><directive module="core">ProtocolsHonorOrder</directive></seealso>
+</directivesynopsis>
+
+
+<directivesynopsis>
+ <name>ProtocolsHonorOrder</name>
+ <description>Protocols available for a server/virtual host</description>
+ <syntax>ProtocolsHonorOrder On|Off</syntax>
+ <default>ProtocolsHonorOrder Off</default>
+ <contextlist><context>server config</context><context>virtual host</context></contextlist>
+ <compatibility>Only available from Apache 2.4.17 and later.</compatibility>
+
+ <usage>
+ <p>This directive specifies if the server should honor the order in which
+ the <directive>Protocols</directive> directive lists protocols.</p>
+
+ <p>By default, a client supplies a list of supported protocols and the server
+ selects an available one from that list in the given order.</p>
+
+ <p>With <directive>ProtocolsHonorOrder</directive> set to <code>on</code>, the
+ client ordering does not matter and only the ordering in the server
+ settings influences the outcome of the protocol negotiation.</p>
+
+ </usage>
+ <seealso><directive module="core">Protocols</directive></seealso>
+</directivesynopsis>
+
+
<directivesynopsis>
<name>RLimitCPU</name>
<description>Limits the CPU consumption of processes launched
apr_array_header_t *protocols;
+ int protocols_honor_order;
} core_server_config;
/* for AddOutputFiltersByType in core.c */
conf->trace_enable = AP_TRACE_UNSET;
conf->protocols = apr_array_make(a, 5, sizeof(const char *));
+ conf->protocols_honor_order = -1;
return (void *)conf;
}
? 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;
}
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)
{
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 }
};
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,
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;
}