From 68ad3a42f7409ea2556adb4f94388513a8140910 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 22 Oct 2018 11:49:15 +0200 Subject: [PATCH] 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. --- doc/configuration.txt | 34 ++++++++++++++++++++++++++++++++++ include/proto/connection.h | 17 +++++++++++++++-- include/types/connection.h | 3 ++- include/types/proxy.h | 2 +- src/cfgparse.c | 15 +++++++++++++++ 5 files changed, 67 insertions(+), 4 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 9cc2a6744..b4c67c6a6 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -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 option httpchk diff --git a/include/proto/connection.h b/include/proto/connection.h index 47825a05e..1aa0ed909 100644 --- a/include/proto/connection.h +++ b/include/proto/connection.h @@ -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; diff --git a/include/types/connection.h b/include/types/connection.h index 827df36f0..889decb6c 100644 --- a/include/types/connection.h +++ b/include/types/connection.h @@ -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 { diff --git a/include/types/proxy.h b/include/types/proxy.h index b5f5b9b40..da098485e 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -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 */ diff --git a/src/cfgparse.c b/src/cfgparse.c index a262404bb..8d8b6ea32 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -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;