MINOR: http-fetch: Add an option to 'query" to get the QS with the '?'

As mentionned by Thayne McCombs in #2728, it could be handy to have a sample
fetch function to retrieve the query string with the question mark
character.

Indeed, for now, "query" sample fetch function already extract the query
string from the path, but the question mark character is not
included. Instead of adding a new sample fetch function with a too similar
name, an optional argument is added to "query". If "with_qm" is passed as
argument, the question mark will be included in the query string, but only
if it is not empty.

Thanks to this patch, the following rule:

  http-request redirect location /destination?%[query] if { -m found query }  some_condition
  http-request redirect location /destination if some_condition

can now be expressed this way:

  http-request redirect location /destination%[query(with_qm)] if some_condition
This commit is contained in:
Christopher Faulet 2024-11-15 17:25:47 +01:00
parent 2a5da31cce
commit 17d4e6eaf9
2 changed files with 35 additions and 4 deletions

View File

@ -25201,7 +25201,7 @@ http_first_req boolean
method integer method integer
path string path string
pathq string pathq string
query string query([<options>]) string
req.hdr_names([<delim>]) string req.hdr_names([<delim>]) string
req.ver string req.ver string
req_ver string req_ver string
@ -25661,13 +25661,20 @@ pathq : string
accept-unsafe-violations-in-http-request", then this fragment part will be accept-unsafe-violations-in-http-request", then this fragment part will be
accepted and will also appear in the path. accepted and will also appear in the path.
query : string query([<options>]) : string
This extracts the request's query string, which starts after the first This extracts the request's query string, which starts after the first
question mark. If no question mark is present, this fetch returns nothing. If question mark. If no question mark is present, this fetch returns nothing. If
a question mark is present but nothing follows, it returns an empty string. a question mark is present but nothing follows, it returns an empty string.
This means it's possible to easily know whether a query string is present This means it's possible to easily know whether a query string is present
using the "found" matching method. This fetch is the complement of "path" using the "found" matching method. This fetch is the complement of "path"
which stops before the question mark. which stops before the question mark and of "query_string", which include the
question mark.
An optional parameter may be used to customize the return value. Following
options are supported:
- with_qm : Include the question mark at the beginning ot the query string,
if not empty.
req.hdr_names([<delim>]) : string req.hdr_names([<delim>]) : string
This builds a string made from the concatenation of all header names as they This builds a string made from the concatenation of all header names as they

View File

@ -1284,6 +1284,9 @@ static int smp_fetch_query(const struct arg *args, struct sample *smp, const cha
return 0; return 0;
} while (*ptr++ != '?'); } while (*ptr++ != '?');
if (ptr != end && args[0].type == ARGT_SINT && args[0].data.sint == 1)
ptr--;
smp->data.type = SMP_T_STR; smp->data.type = SMP_T_STR;
smp->data.u.str.area = ptr; smp->data.u.str.area = ptr;
smp->data.u.str.data = end - ptr; smp->data.u.str.data = end - ptr;
@ -2224,6 +2227,27 @@ int val_hdr(struct arg *arg, char **err_msg)
return 1; return 1;
} }
int val_query(struct arg *args, char **err_msg)
{
if (args[0].type == ARGT_STOP)
return 1;
if (args[0].type != ARGT_STR) {
memprintf(err_msg, "first argument must be a string");
return 0;
}
if (chunk_strcmp(&args[0].data.str, "with_qm") != 0) {
memprintf(err_msg, "supported options are: 'with_qm'");
return 0;
}
chunk_destroy(&args[0].data.str);
args[0].type = ARGT_SINT;
args[0].data.sint = 1;
return 1;
}
/************************************************************************/ /************************************************************************/
/* All supported sample fetch keywords must be declared here. */ /* All supported sample fetch keywords must be declared here. */
/************************************************************************/ /************************************************************************/
@ -2274,7 +2298,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
{ "method", smp_fetch_meth, 0, NULL, SMP_T_METH, SMP_USE_HRQHP }, { "method", smp_fetch_meth, 0, NULL, SMP_T_METH, SMP_USE_HRQHP },
{ "path", smp_fetch_path, 0, NULL, SMP_T_STR, SMP_USE_HRQHV }, { "path", smp_fetch_path, 0, NULL, SMP_T_STR, SMP_USE_HRQHV },
{ "pathq", smp_fetch_path, 0, NULL, SMP_T_STR, SMP_USE_HRQHV }, { "pathq", smp_fetch_path, 0, NULL, SMP_T_STR, SMP_USE_HRQHV },
{ "query", smp_fetch_query, 0, NULL, SMP_T_STR, SMP_USE_HRQHV }, { "query", smp_fetch_query, ARG1(0,STR), val_query, SMP_T_STR, SMP_USE_HRQHV },
/* HTTP protocol on the request path */ /* HTTP protocol on the request path */
{ "req.proto_http", smp_fetch_proto_http, 0, NULL, SMP_T_BOOL, SMP_USE_HRQHP }, { "req.proto_http", smp_fetch_proto_http, 0, NULL, SMP_T_BOOL, SMP_USE_HRQHP },