MINOR: http_fetch: Add case-insensitive argument for url_param/urlp_val

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.
This commit is contained in:
Martin DOLEZ 2023-03-28 09:06:05 -04:00 committed by Willy Tarreau
parent 110e4a8733
commit 28c5f40ad6
2 changed files with 35 additions and 26 deletions

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

View 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 */ },
}};