From 17d4e6eaf9f5fa5f13fad74b76ec2d31408abf6a Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Fri, 15 Nov 2024 17:25:47 +0100 Subject: [PATCH] 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 --- doc/configuration.txt | 13 ++++++++++--- src/http_fetch.c | 26 +++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index a0e49ddb39..bf95d051ae 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -25201,7 +25201,7 @@ http_first_req boolean method integer path string pathq string -query string +query([]) string req.hdr_names([]) 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 accepted and will also appear in the path. -query : string +query([]) : string 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 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 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([]) : string This builds a string made from the concatenation of all header names as they diff --git a/src/http_fetch.c b/src/http_fetch.c index ad1e8c5435..28fe8ae7a3 100644 --- a/src/http_fetch.c +++ b/src/http_fetch.c @@ -1284,6 +1284,9 @@ static int smp_fetch_query(const struct arg *args, struct sample *smp, const cha return 0; } while (*ptr++ != '?'); + if (ptr != end && args[0].type == ARGT_SINT && args[0].data.sint == 1) + ptr--; + smp->data.type = SMP_T_STR; smp->data.u.str.area = ptr; smp->data.u.str.data = end - ptr; @@ -2224,6 +2227,27 @@ int val_hdr(struct arg *arg, char **err_msg) 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. */ /************************************************************************/ @@ -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 }, { "path", 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 */ { "req.proto_http", smp_fetch_proto_http, 0, NULL, SMP_T_BOOL, SMP_USE_HRQHP },