]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
new directive ProtocolsHonorOrder, added documentation for Protocols feature, changed...
authorStefan Eissing <icing@apache.org>
Thu, 13 Aug 2015 15:33:07 +0000 (15:33 +0000)
committerStefan Eissing <icing@apache.org>
Thu, 13 Aug 2015 15:33:07 +0000 (15:33 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1695727 13f79535-47bb-0310-9956-ffa450edef68

docs/manual/mod/core.xml
include/http_core.h
server/core.c
server/protocol.c

index e9f0596a4b6012b6970ca782aa2046b640b5a02d..f3eb55ce79be468f274dfb382141c76f623ea0e4 100644 (file)
@@ -3710,6 +3710,71 @@ Protocol https
 </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
index 0b19deedd4e3b443892f28356ace66a1b9c5a3dc..13196e1059d36349f033c59b9d6a545315970b43 100644 (file)
@@ -710,6 +710,7 @@ typedef struct {
 
 
     apr_array_header_t *protocols;
+    int protocols_honor_order;
 } core_server_config;
 
 /* for AddOutputFiltersByType in core.c */
index 97c0b1c862f5a912e7f81f0d582791dfd3d3ec98..e7383970a77f1c4c4b4133051a7fcd7da109f903 100644 (file)
@@ -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 }
 };
 
index bf1dc518cfa1c26ac27e88c00e1f975c008be9c4..4577d23383e3e86920a3a4e820df420775d16c95 100644 (file)
@@ -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;
             }