]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: proxy: add a new option "http-use-htx"
authorWilly Tarreau <w@1wt.eu>
Mon, 22 Oct 2018 09:49:15 +0000 (11:49 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 23 Oct 2018 08:22:36 +0000 (10:22 +0200)
This option makes a proxy use only HTX-compatible muxes instead of the
HTTP-compatible ones for HTTP modes. It must be set on both ends, this
is checked at parsing time.

doc/configuration.txt
include/proto/connection.h
include/types/connection.h
include/types/proxy.h
src/cfgparse.c

index 9cc2a67444581efd7d3ce24d4a3760f7cd8a6e73..b4c67c6a61c42a60d729b85a348343ccb1f129ab 100644 (file)
@@ -2114,6 +2114,7 @@ option http-pretend-keepalive        (*)  X          -         X         X
 option http-server-close             (*)  X          X         X         X
 option http-tunnel                   (*)  X          X         X         -
 option http-use-proxy-header         (*)  X          X         X         -
+option http-use-htx                  (*)  X          X         X         X
 option httpchk                            X          -         X         X
 option httpclose                     (*)  X          X         X         X
 option httplog                            X          X         X         X
@@ -6018,6 +6019,39 @@ no option http-use-proxy-header
   See also : "option httpclose", and "option http-server-close".
 
 
+option http-use-htx
+no option http-use-htx
+  Switch to the new HTX internal representation for HTTP protocol elements
+  May be used in sections :   defaults | frontend | listen | backend
+                                 yes   |    yes   |   yes  |   yes
+  Arguments : none
+
+  By default, the HTTP protocol is processed as-is. Inserting, deleting, or
+  modifying a header field requires to rewrite the affected part in the buffer
+  and to move the buffer's tail accordingly. Since this principle has deep
+  roots in haproxy, the HTTP/2 protocol is converted to HTTP/1.1 before being
+  processed this way. It also results in the inability to establish HTTP/2
+  connections to servers because of the loss of HTTP/2 semantics in the HTTP/1
+  representation.
+
+  HTX is the name of a totally new native internal representation for the HTTP
+  protocol, that is agnostic to the version and aims at preserving semantics
+  all along the chain. It relies on a fast parsing, tokenizing and indexing of
+  the protocol elements so that no more memory moves are necessary and that
+  most elements are directly accessed. This mechanism is still limited to the
+  most basic operations (no compression, filters, Lua, applets, cache, etc).
+  But it supports using either HTTP/1 or HTTP/2 on any side regardless of the
+  other side's version.
+
+  This option indicates that HTX needs to be used. It will cause errors to be
+  emitted if incompatible features are used, but will allow H2 to be selected
+  as a server protocol. It is recommended to use this option on new reasonably
+  simple configurations, but since the feature still has incomplete functional
+  coverage, it is not enabled by default.
+
+  See also : "mode http"
+
+
 option httpchk
 option httpchk <uri>
 option httpchk <method> <uri>
index 47825a05edb5ec44f860b2529ffa8530da765ede..1aa0ed909433c16238ab43c892d7af8307fecf41 100644 (file)
@@ -971,7 +971,14 @@ static inline int conn_install_mux_fe(struct connection *conn, void *ctx)
                struct ist mux_proto;
                const char *alpn_str = NULL;
                int alpn_len = 0;
-               int mode = (1 << (bind_conf->frontend->mode == PR_MODE_HTTP));
+               int mode;
+
+               if (bind_conf->frontend->mode == PR_MODE_TCP)
+                       mode = PROTO_MODE_TCP;
+               else if (bind_conf->frontend->options2 & PR_O2_USE_HTX)
+                       mode = PROTO_MODE_HTX;
+               else
+                       mode = PROTO_MODE_HTTP;
 
                conn_get_alpn(conn, &alpn_str, &alpn_len);
                mux_proto = ist2(alpn_str, alpn_len);
@@ -1003,7 +1010,13 @@ static inline int conn_install_mux_be(struct connection *conn, void *ctx)
        else {
                int mode;
 
-               mode = (1 << (prx->mode == PR_MODE_HTTP));
+               if (prx->mode == PR_MODE_TCP)
+                       mode = PROTO_MODE_TCP;
+               else if (prx->options2 & PR_O2_USE_HTX)
+                       mode = PROTO_MODE_HTX;
+               else
+                       mode = PROTO_MODE_HTTP;
+
                mux_ops = conn_get_best_mux(conn, ist(NULL), PROTO_SIDE_BE, mode);
                if (!mux_ops)
                        return -1;
index 827df36f094bf1763e5f9c255efa8538541810e4..889decb6c6de2a9c1dfe9f17ecf322bf94ba8d3c 100644 (file)
@@ -425,7 +425,8 @@ enum proto_proxy_mode {
        PROTO_MODE_NONE = 0,
        PROTO_MODE_TCP  = 1 << 0, // must not be changed!
        PROTO_MODE_HTTP = 1 << 1, // must not be changed!
-       PROTO_MODE_ANY  = PROTO_MODE_TCP | PROTO_MODE_HTTP,
+       PROTO_MODE_HTX  = 1 << 2, // must not be changed!
+       PROTO_MODE_ANY  = PROTO_MODE_TCP | PROTO_MODE_HTTP, // note: HTX is experimental and must not appear here
 };
 
 enum proto_proxy_side {
index b5f5b9b403524bdadca3706d7da6e545d0e61d59..da098485ed1b6b99203f1d2d3d0d01d2cc8e1b68 100644 (file)
@@ -151,7 +151,7 @@ enum PR_SRV_STATE_FILE {
 #define PR_O2_SRC_ADDR 0x00100000      /* get the source ip and port for logs */
 
 #define PR_O2_FAKE_KA   0x00200000      /* pretend we do keep-alive with server eventhough we close */
-/* unused: 0x00400000 */
+#define PR_O2_USE_HTX   0x00400000      /* use the HTX representation for the HTTP protocol */
 #define PR_O2_EXP_NONE  0x00000000      /* http-check : no expect rule */
 #define PR_O2_EXP_STS   0x00800000      /* http-check expect status */
 #define PR_O2_EXP_RSTS  0x01000000      /* http-check expect rstatus */
index a262404bb92094518260cbdb3b7f55b42a8781b3..8d8b6ea32695f14f49d9d9734566ce55b98afa0f 100644 (file)
@@ -208,6 +208,7 @@ static const struct cfg_opt cfg_opts2[] =
        { "http-use-proxy-header",        PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
        { "http-pretend-keepalive",       PR_O2_FAKE_KA,   PR_CAP_BE, 0, PR_MODE_HTTP },
        { "http-no-delay",                PR_O2_NODELAY,   PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
+       { "http-use-htx",                 PR_O2_USE_HTX,   PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
        { NULL, 0, 0, 0 }
 };
 
@@ -7792,6 +7793,13 @@ int check_config_validity()
                                         proxy_mode_str(target->mode), proxy_type_str(target), target->id,
                                         target->conf.file, target->conf.line);
                                cfgerr++;
+                       } else if ((curproxy->options2 ^ target->options2) & PR_O2_USE_HTX) {
+                               ha_alert("%s %s '%s' (%s:%d) tries to use %s %s '%s' (%s:%d) as its default backend, both of which disagree on 'option http-use-htx'.\n",
+                                        proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
+                                        curproxy->conf.file, curproxy->conf.line,
+                                        proxy_mode_str(target->mode), proxy_type_str(target), target->id,
+                                        target->conf.file, target->conf.line);
+                               cfgerr++;
                        } else {
                                free(curproxy->defbe.name);
                                curproxy->defbe.be = target;
@@ -7872,6 +7880,13 @@ int check_config_validity()
                                         proxy_mode_str(target->mode), proxy_type_str(target), target->id,
                                         target->conf.file, target->conf.line);
                                cfgerr++;
+                       } else if ((curproxy->options2 ^ target->options2) & PR_O2_USE_HTX) {
+                               ha_alert("%s %s '%s' (%s:%d) tries to use %s %s '%s' (%s:%d) in a 'use_backend' rule, both of which disagree on 'option http-use-htx'.\n",
+                                        proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
+                                        curproxy->conf.file, curproxy->conf.line,
+                                        proxy_mode_str(target->mode), proxy_type_str(target), target->id,
+                                        target->conf.file, target->conf.line);
+                               cfgerr++;
                        } else {
                                free((void *)rule->be.name);
                                rule->be.backend = target;