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.
This commit is contained in:
Willy Tarreau 2018-10-22 11:49:15 +02:00
parent 955188d37d
commit 68ad3a42f7
5 changed files with 67 additions and 4 deletions

View 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>

View 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;

View 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 {

View 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 */

View 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;