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 recommended to use "option http-buffer-request" to be sure to wait, as much
as possible, for the request's body. 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 This fetch assumes that the body of the POST request is url-encoded. The user
can check if the "content-type" contains the value can check if the "content-type" contains the value
"application/x-www-form-urlencoded". This extracts the first occurrence of the "application/x-www-form-urlencoded". This extracts the first occurrence of the
parameter <name> in the body, which ends before '&'. The parameter name is 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 case-sensitive, unless "i" is added as a second argument. If no name is
one will be returned. The result is a string corresponding to the value of the given, any parameter will match, and the first one will be returned. The
parameter <name> as presented in the request body (no URL decoding is result is a string corresponding to the value of the parameter <name> as
performed). Note that the ACL version of this fetch iterates over multiple presented in the request body (no URL decoding is performed). Note that the
parameters and will iteratively report all parameters values if no name is ACL version of this fetch iterates over multiple parameters and will
given. iteratively report all parameters values if no name is given.
req.body_len : integer req.body_len : integer
This returns the length of the HTTP request's available body in bytes. It may 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 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.. not specified in the request, port 80 is assumed..
urlp([<name>[,<delim>]]) : string urlp([<name>[,<delim>[,i]]]) : string
url_param([<name>[,<delim>]]) : string url_param([<name>[,<delim>[,i]]]) : string
This extracts the first occurrence of the parameter <name> in the query This extracts the first occurrence of the parameter <name> in the query
string, which begins after either '?' or <delim>, and which ends before '&', string, which begins after either '?' or <delim>, and which ends before '&',
';' or <delim>. The parameter name is case-sensitive. If no name is given, ';' or <delim>. The parameter name is case-sensitive, unless"i" is added as a
any parameter will match, and the first one will be returned. The result is third argument. If no name is given, any parameter will match, and the first
a string corresponding to the value of the parameter <name> as presented in one will be returned. The result is a string corresponding to the value of the
the request (no URL decoding is performed). This can be used for session parameter <name> as presented in the request (no URL decoding is performed).
stickiness based on a client ID, to extract an application cookie passed as a This can be used for session stickiness based on a client ID, to extract an
URL parameter, or in ACLs to apply some checks. Note that the ACL version of application cookie passed as a URL parameter, or in ACLs to apply some checks.
this fetch iterates over multiple parameters and will iteratively report all Note that the ACL version of this fetch iterates over multiple parameters and
parameters values if no name is given will iteratively report all parameters values if no name is given
ACL derivatives : ACL derivatives :
urlp(<name>[,<delim>]) : exact string match urlp(<name>[,<delim>]) : exact string match
@ -21960,7 +21960,7 @@ url_param([<name>[,<delim>]]) : string
# match http://example.com/foo;JSESSIONID=some_id # match http://example.com/foo;JSESSIONID=some_id
stick on urlp(JSESSIONID,;) 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 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 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. 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 = '?'; char delim = '?';
const char *name; const char *name;
int name_len; 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)) (args[1].type && args[1].type != ARGT_STR) ||
(args[2].type && args[2].type != ARGT_STR))
return 0; return 0;
name = ""; 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) if (args[1].type && *args[1].data.str.area)
delim = *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 if (!smp->ctx.a[0]) { // first call, find the query string
struct htx *htx = smp_prefetch_htx(smp, chn, NULL, 1); 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 /* 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); struct channel *chn = SMP_REQ_CHN(smp);
const char *name; const char *name;
int name_len; 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; return 0;
name = ""; 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; 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 if (!smp->ctx.a[0]) { // first call, find the query string
struct htx *htx = smp_prefetch_htx(smp, chn, NULL, 1); struct htx *htx = smp_prefetch_htx(smp, chn, NULL, 1);
struct buffer *temp; 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 /* 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", 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_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_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", 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 }, { "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 }, { "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_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_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 }, { "url_param", smp_fetch_url_param, ARG3(0,STR,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" , smp_fetch_url_param, ARG3(0,STR,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 }, { "urlp_val", smp_fetch_url_param_val, ARG3(0,STR,STR,STR), NULL, SMP_T_SINT, SMP_USE_HRQHV },
{ /* END */ }, { /* END */ },
}}; }};