MINOR: proxy: add a new option "http-use-htx"
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.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 9cc2a67..b4c67c6 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -2114,6 +2114,7 @@
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 @@
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>
diff --git a/include/proto/connection.h b/include/proto/connection.h
index 47825a0..1aa0ed9 100644
--- a/include/proto/connection.h
+++ b/include/proto/connection.h
@@ -971,7 +971,14 @@
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 @@
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;
diff --git a/include/types/connection.h b/include/types/connection.h
index 827df36..889decb 100644
--- a/include/types/connection.h
+++ b/include/types/connection.h
@@ -425,7 +425,8 @@
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 {
diff --git a/include/types/proxy.h b/include/types/proxy.h
index b5f5b9b..da09848 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -151,7 +151,7 @@
#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 */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index a262404..8d8b6ea 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -208,6 +208,7 @@
{ "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 @@
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 @@
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;