diff --git a/doc/configuration.txt b/doc/configuration.txt index 8f8900b0f..fce569853 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -17052,6 +17052,16 @@ hmac(,) Please note that this converter is only available when HAProxy has been compiled with USE_OPENSSL. +host_only + Converts a string which contains a Host header value and removes its port. + The input must respect the format of the host header value + (rfc9110#section-7.2). It will support that kind of input: hostname, + hostname:80, 127.0.0.1, 127.0.0.1:80, [::1], [::1]:80. + + This converter also sets the string in lowercase. + + See also: "port_only" converter which will return the port. + http_date([]) Converts an integer supposed to contain a date since epoch to a string representing this date in a format suitable for use in HTTP header fields. If @@ -17494,6 +17504,17 @@ or() This prefix is followed by a name. The separator is a '.'. The name may only contain characters 'a-z', 'A-Z', '0-9', '.' and '_'. +port_only + Converts a string which contains a Host header value into an integer by + returning its port. + The input must respect the format of the host header value + (rfc9110#section-7.2). It will support that kind of input: hostname, + hostname:80, 127.0.0.1, 127.0.0.1:80, [::1], [::1]:80. + + If no port were provided in the input, it will return 0. + + See also: "host_only" converter which will return the host. + protobuf(,[]) This extracts the protocol buffers message field in raw mode of an input binary sample representation of a protocol buffer message with as field diff --git a/src/sample.c b/src/sample.c index 50ae76b6e..852cd0418 100644 --- a/src/sample.c +++ b/src/sample.c @@ -3266,6 +3266,58 @@ static int sample_conv_strcmp(const struct arg *arg_p, struct sample *smp, void smp->data.type = SMP_T_SINT; return 1; } +/* + * This converter can takes a Host header value as defined by rfc9110#section-7.2 + * Host = uri-host [ ":" port ] ; + * It returns the uri-host value in lowecase with the port stripped. + */ +static int sample_conv_host_only(const struct arg *arg_p, struct sample *smp, void *private) +{ + /* Working cases: hostname00, hostname00:80, 127.0.0.1, 127.0.0.1:80, [::1], [::1]:80 */ + char *beg = smp->data.u.str.area; + char *end = smp->data.u.str.area + smp->data.u.str.data - 1; + char *p; + + for (p = end; p >= beg; p--) { + if (*p == ':' || *p == ']') + break; + } + + if (p >= beg && *p == ':') + smp->data.u.str.data = p - beg; + /* if no port part was found, the hostname is the whole string */ + + smp->data.type = SMP_T_STR; + + return sample_conv_str2lower(arg_p, smp, NULL); +} + +/* + * This converter can takes a Host header value as defined by rfc9110#section-7.2 + * Host = uri-host [ ":" port ] ; + * It returns the port value as a int. + */ +static int sample_conv_port_only(const struct arg *arg_p, struct sample *smp, void *private) +{ + /* Working cases: hostname00, hostname00:80, 127.0.0.1, 127.0.0.1:80, [::1], [::1]:80 */ + char *beg = smp->data.u.str.area; + char *end = smp->data.u.str.area + smp->data.u.str.data - 1; + char *p; + + for (p = end; p >= beg; p--) { + if (*p == ':' || *p == ']') + break; + } + + smp->data.type = SMP_T_SINT; + if (p >= beg && *p == ':' && ++p <= end) { + smp->data.u.sint = strl2ui(p, smp->data.u.str.data + smp->data.u.str.area - p); + } else { + smp->data.u.sint = 0; + } + return 1; +} + /* Takes a boolean as input. Returns the first argument if that boolean is true and * the second argument otherwise. @@ -4350,6 +4402,8 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH, { { "regsub", sample_conv_regsub, ARG3(2,REG,STR,STR), sample_conv_regsub_check, SMP_T_STR, SMP_T_STR }, { "sha1", sample_conv_sha1, 0, NULL, SMP_T_BIN, SMP_T_BIN }, { "strcmp", sample_conv_strcmp, ARG1(1,STR), smp_check_strcmp, SMP_T_STR, SMP_T_SINT }, + { "host_only", sample_conv_host_only, 0, NULL, SMP_T_STR, SMP_T_STR }, + { "port_only", sample_conv_port_only, 0, NULL, SMP_T_STR, SMP_T_SINT }, /* gRPC converters. */ { "ungrpc", sample_conv_ungrpc, ARG2(1,PBUF_FNUM,STR), sample_conv_protobuf_check, SMP_T_BIN, SMP_T_BIN },