]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: http_fetch: Add case-insensitive argument for url_param/urlp_val
authorMartin DOLEZ <martin@dolez.fr>
Tue, 28 Mar 2023 13:06:05 +0000 (09:06 -0400)
committerWilly Tarreau <w@1wt.eu>
Thu, 30 Mar 2023 12:11:25 +0000 (14:11 +0200)
This commit adds a new optional argument to smp_fetch_url_param
and smp_fetch_url_param_val that makes the parameter key comparison
case-insensitive.
Now users can retrieve URL parameters regardless of their case,
allowing to match parameters in case insensitive application.
Doc was updated.

doc/configuration.txt
src/http_fetch.c

index 38f93c7a63a64ce753807ab5c5094b82d528153f..e236f0a87ca31a3e45e86fad58f37d6602fb71aa 100644 (file)
@@ -21401,17 +21401,17 @@ req.body : binary
   recommended to use "option http-buffer-request" to be sure to wait, as much
   as possible, for the request's body.
 
-req.body_param([<name>) : string
+req.body_param([<name>[,i]]) : string
   This fetch assumes that the body of the POST request is url-encoded. The user
   can check if the "content-type" contains the value
   "application/x-www-form-urlencoded". This extracts the first occurrence of the
   parameter <name> in the body, which ends before '&'. The parameter name is
-  case-sensitive. If no name is given, any parameter will match, and the first
-  one will be returned. The result is a string corresponding to the value of the
-  parameter <name> as presented in the request body (no URL decoding is
-  performed). Note that the ACL version of this fetch iterates over multiple
-  parameters and will iteratively report all parameters values if no name is
-  given.
+  case-sensitive, unless "i" is added as a second argument. If no name is
+  given, any parameter will match, and the first one will be returned. The
+  result is a string corresponding to the value of the parameter <name> as
+  presented in the request body (no URL decoding is performed). Note that the
+  ACL version of this fetch iterates over multiple parameters and will
+  iteratively report all parameters values if no name is given.
 
 req.body_len : integer
   This returns the length of the HTTP request's available body in bytes. It may
@@ -21930,18 +21930,18 @@ url_port : integer
   This extracts the port part from the request's URL. Note that if the port is
   not specified in the request, port 80 is assumed..
 
-urlp([<name>[,<delim>]]) : string
-url_param([<name>[,<delim>]]) : string
+urlp([<name>[,<delim>[,i]]]) : string
+url_param([<name>[,<delim>[,i]]]) : string
   This extracts the first occurrence of the parameter <name> in the query
   string, which begins after either '?' or <delim>, and which ends before '&',
-  ';' or <delim>. The parameter name is case-sensitive. If no name is given,
-  any parameter will match, and the first one will be returned. The result is
-  a string corresponding to the value of the parameter <name> as presented in
-  the request (no URL decoding is performed). This can be used for session
-  stickiness based on a client ID, to extract an application cookie passed as a
-  URL parameter, or in ACLs to apply some checks. Note that the ACL version of
-  this fetch iterates over multiple parameters and will iteratively report all
-  parameters values if no name is given
+  ';' or <delim>. The parameter name is case-sensitive, unless"i" is added as a
+  third argument. If no name is given, any parameter will match, and the first
+  one will be returned. The result is a string corresponding to the value of the
+  parameter <name> as presented in the request (no URL decoding is performed).
+  This can be used for session stickiness based on a client ID, to extract an
+  application cookie passed as a URL parameter, or in ACLs to apply some checks.
+  Note that the ACL version of this fetch iterates over multiple parameters and
+  will iteratively report all parameters values if no name is given
 
   ACL derivatives :
     urlp(<name>[,<delim>])     : exact string match
@@ -21960,7 +21960,7 @@ url_param([<name>[,<delim>]]) : string
       # match http://example.com/foo;JSESSIONID=some_id
       stick on urlp(JSESSIONID,;)
 
-urlp_val([<name>[,<delim>]]) : integer
+urlp_val([<name>[,<delim>[,i]]]) : integer
   See "urlp" above. This one extracts the URL parameter <name> in the request
   and converts it to an integer value. This can be used for session stickiness
   based on a user ID for example, or with ACLs to match a page number or price.
index 270ef97d28f1c2130451d5a99ee082a8afd00f26..1775bc68b1ad1df56747643986437669d3c61a72 100644 (file)
@@ -1890,9 +1890,11 @@ static int smp_fetch_url_param(const struct arg *args, struct sample *smp, const
        char delim = '?';
        const char *name;
        int name_len;
+       char insensitive = 0;
 
        if ((args[0].type && args[0].type != ARGT_STR) ||
-           (args[1].type && args[1].type != ARGT_STR))
+               (args[1].type && args[1].type != ARGT_STR) ||
+           (args[2].type && args[2].type != ARGT_STR))
                return 0;
 
        name = "";
@@ -1904,6 +1906,8 @@ static int smp_fetch_url_param(const struct arg *args, struct sample *smp, const
 
        if (args[1].type && *args[1].data.str.area)
                delim = *args[1].data.str.area;
+       if (args[2].type && *args[2].data.str.area == 'i')
+               insensitive = 1;
 
        if (!smp->ctx.a[0]) { // first call, find the query string
                struct htx *htx = smp_prefetch_htx(smp, chn, NULL, 1);
@@ -1926,7 +1930,7 @@ static int smp_fetch_url_param(const struct arg *args, struct sample *smp, const
                 */
        }
 
-       return smp_fetch_param(delim, name, name_len, args, smp, kw, private, 0);
+       return smp_fetch_param(delim, name, name_len, args, smp, kw, private, insensitive);
 }
 
 /* This function iterates over each parameter of the body. This requires
@@ -1941,8 +1945,10 @@ static int smp_fetch_body_param(const struct arg *args, struct sample *smp, cons
        struct channel *chn = SMP_REQ_CHN(smp);
        const char *name;
        int name_len;
+       char insensitive = 0;
 
-       if (args[0].type && args[0].type != ARGT_STR)
+       if ((args[0].type && args[0].type != ARGT_STR) ||
+           (args[1].type && args[1].type != ARGT_STR))
                return 0;
 
        name = "";
@@ -1952,6 +1958,9 @@ static int smp_fetch_body_param(const struct arg *args, struct sample *smp, cons
                name_len = args[0].data.str.data;
        }
 
+       if (args[1].type && *args[1].data.str.area == 'i')
+               insensitive = 1;
+
        if (!smp->ctx.a[0]) { // first call, find the query string
                struct htx *htx = smp_prefetch_htx(smp, chn, NULL, 1);
                struct buffer *temp;
@@ -1984,7 +1993,7 @@ static int smp_fetch_body_param(const struct arg *args, struct sample *smp, cons
 
        }
 
-       return smp_fetch_param('&', name, name_len, args, smp, kw, private, 0);
+       return smp_fetch_param('&', name, name_len, args, smp, kw, private, insensitive);
 }
 
 /* Return the signed integer value for the specified url parameter (see url_param
@@ -2179,7 +2188,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
        { "req.body",           smp_fetch_body,               0,                NULL,    SMP_T_BIN,  SMP_USE_HRQHV },
        { "req.body_len",       smp_fetch_body_len,           0,                NULL,    SMP_T_SINT, SMP_USE_HRQHV },
        { "req.body_size",      smp_fetch_body_size,          0,                NULL,    SMP_T_SINT, SMP_USE_HRQHV },
-       { "req.body_param",     smp_fetch_body_param,         ARG1(0,STR),      NULL,    SMP_T_BIN,  SMP_USE_HRQHV },
+       { "req.body_param",     smp_fetch_body_param,         ARG2(0,STR,STR),  NULL,    SMP_T_BIN,  SMP_USE_HRQHV },
 
        { "req.hdrs",           smp_fetch_hdrs,               0,                NULL,    SMP_T_BIN,  SMP_USE_HRQHV },
        { "req.hdrs_bin",       smp_fetch_hdrs_bin,           0,                NULL,    SMP_T_BIN,  SMP_USE_HRQHV },
@@ -2239,9 +2248,9 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
        { "url32+src",          smp_fetch_url32_src,          0,                NULL,    SMP_T_BIN,  SMP_USE_HRQHV },
        { "url_ip",             smp_fetch_url_ip,             0,                NULL,    SMP_T_IPV4, SMP_USE_HRQHV },
        { "url_port",           smp_fetch_url_port,           0,                NULL,    SMP_T_SINT, SMP_USE_HRQHV },
-       { "url_param",          smp_fetch_url_param,          ARG2(0,STR,STR),  NULL,    SMP_T_STR,  SMP_USE_HRQHV },
-       { "urlp"     ,          smp_fetch_url_param,          ARG2(0,STR,STR),  NULL,    SMP_T_STR,  SMP_USE_HRQHV },
-       { "urlp_val",           smp_fetch_url_param_val,      ARG2(0,STR,STR),  NULL,    SMP_T_SINT, SMP_USE_HRQHV },
+       { "url_param",          smp_fetch_url_param,          ARG3(0,STR,STR,STR),  NULL,    SMP_T_STR,  SMP_USE_HRQHV },
+       { "urlp"     ,          smp_fetch_url_param,          ARG3(0,STR,STR,STR),  NULL,    SMP_T_STR,  SMP_USE_HRQHV },
+       { "urlp_val",           smp_fetch_url_param_val,      ARG3(0,STR,STR,STR),  NULL,    SMP_T_SINT, SMP_USE_HRQHV },
 
        { /* END */ },
 }};