From: Martin DOLEZ Date: Tue, 28 Mar 2023 13:06:05 +0000 (-0400) Subject: MINOR: http_fetch: Add case-insensitive argument for url_param/urlp_val X-Git-Tag: v2.8-dev7~139 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=28c5f40ad6a1a0be46193a3d8b33c2d5b32aed0a;p=thirdparty%2Fhaproxy.git 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. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 38f93c7a63..e236f0a87c 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -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([) : string +req.body_param([[,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 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 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 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([[,]]) : string -url_param([[,]]) : string +urlp([[,[,i]]]) : string +url_param([[,[,i]]]) : string This extracts the first occurrence of the parameter in the query string, which begins after either '?' or , and which ends before '&', - ';' or . 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 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 . 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 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([,]) : exact string match @@ -21960,7 +21960,7 @@ url_param([[,]]) : string # match http://example.com/foo;JSESSIONID=some_id stick on urlp(JSESSIONID,;) -urlp_val([[,]]) : integer +urlp_val([[,[,i]]]) : integer See "urlp" above. This one extracts the URL parameter 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. diff --git a/src/http_fetch.c b/src/http_fetch.c index 270ef97d28..1775bc68b1 100644 --- a/src/http_fetch.c +++ b/src/http_fetch.c @@ -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 */ }, }};