]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: sample: add the host_only and port_only converters
authorWilliam Lallemand <wlallemand@haproxy.org>
Fri, 26 Aug 2022 14:21:28 +0000 (16:21 +0200)
committerWilliam Lallemand <wlallemand@haproxy.org>
Fri, 26 Aug 2022 15:00:22 +0000 (17:00 +0200)
Add 2 converters that can manipulate the value of an Host header.
host_only will return the host without any port, and port_only will
return the port.

doc/configuration.txt
src/sample.c

index 8f8900b0fba9cb85469cffe30f45b506616e7221..fce5698533e1e9976b1d85fbfdd07aafcfc0b09b 100644 (file)
@@ -17052,6 +17052,16 @@ hmac(<algorithm>,<key>)
   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([<offset],[<unit>])
   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(<value>)
   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(<field_number>,[<field_type>])
   This extracts the protocol buffers message field in raw mode of an input binary
   sample representation of a protocol buffer message with <field_number> as field
index 50ae76b6e574e7843e0881b9ef281bc30957c5f5..852cd0418f534c9a855cf4228b6c1e3e215f0e1e 100644 (file)
@@ -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  },