mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-20 04:37:04 +00:00
MEDIUM: http: make url_param iterate over multiple occurrences
There are some situations hwere it's desirable to scan multiple occurrences of a same parameter name in the query string. This change ensures this can work, even with an empty name which will then iterate over all parameters.
This commit is contained in:
parent
26ea822190
commit
1ede1daab6
@ -12709,17 +12709,18 @@ url_port : integer
|
||||
restrict access to certain systems through a proxy, for example when combined
|
||||
with option "http_proxy".
|
||||
|
||||
urlp(<name>[,<delim>]) : string
|
||||
url_param(<name>[,<delim>]) : string
|
||||
urlp([<name>[,<delim>]]) : string
|
||||
url_param([<name>[,<delim>]]) : 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. 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
|
||||
';' 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 do not iterate over multiple parameters and stop at the first one
|
||||
as well.
|
||||
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
|
||||
@ -12738,7 +12739,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>])] : 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.
|
||||
|
@ -11488,7 +11488,7 @@ smp_fetch_cookie_val(const struct arg *args, struct sample *smp, const char *kw,
|
||||
*
|
||||
* Example: if path = "/foo/bar/fubar?yo=mama;ye=daddy", and n = 22:
|
||||
*
|
||||
* find_query_string(path, n) points to "yo=mama;ye=daddy" string.
|
||||
* find_query_string(path, n, '?') points to "yo=mama;ye=daddy" string.
|
||||
*/
|
||||
static inline char *find_param_list(char *path, size_t path_l, char delim)
|
||||
{
|
||||
@ -11512,7 +11512,7 @@ static inline int is_param_delimiter(char c, char delim)
|
||||
*/
|
||||
static char*
|
||||
find_url_param_pos(char* query_string, size_t query_string_l,
|
||||
char* url_param_name, size_t url_param_name_l,
|
||||
const char* url_param_name, size_t url_param_name_l,
|
||||
char delim)
|
||||
{
|
||||
char *pos, *last;
|
||||
@ -11534,31 +11534,37 @@ find_url_param_pos(char* query_string, size_t query_string_l,
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a url parameter name, returns its value and size into *value and
|
||||
* *value_l respectively, and returns non-zero. If the parameter is not found,
|
||||
* zero is returned and value/value_l are not touched.
|
||||
* Given a url parameter name and a query string, returns its value and size
|
||||
* into *value and *value_l respectively, and returns non-zero. An empty
|
||||
* url_param_name matches the first available parameter. If the parameter is
|
||||
* not found, zero is returned and value/value_l are not touched.
|
||||
*/
|
||||
static int
|
||||
find_url_param_value(char* path, size_t path_l,
|
||||
char* url_param_name, size_t url_param_name_l,
|
||||
char** value, int* value_l, char delim)
|
||||
find_next_url_param(char* query_string, char *qs_end,
|
||||
const char* url_param_name, size_t url_param_name_l,
|
||||
char** value, int* value_l, char delim)
|
||||
{
|
||||
char *query_string, *qs_end;
|
||||
char *arg_start;
|
||||
char *value_start, *value_end;
|
||||
|
||||
query_string = find_param_list(path, path_l, delim);
|
||||
if (!query_string)
|
||||
return 0;
|
||||
|
||||
qs_end = path + path_l;
|
||||
arg_start = find_url_param_pos(query_string, qs_end - query_string,
|
||||
url_param_name, url_param_name_l,
|
||||
delim);
|
||||
arg_start = query_string;
|
||||
if (url_param_name_l) {
|
||||
arg_start = find_url_param_pos(query_string, qs_end - query_string,
|
||||
url_param_name, url_param_name_l,
|
||||
delim);
|
||||
}
|
||||
if (!arg_start)
|
||||
return 0;
|
||||
|
||||
value_start = arg_start + url_param_name_l + 1;
|
||||
if (!url_param_name_l) {
|
||||
value_start = memchr(arg_start, '=', qs_end - arg_start);
|
||||
if (!value_start)
|
||||
return 0;
|
||||
value_start++;
|
||||
}
|
||||
else
|
||||
value_start = arg_start + url_param_name_l + 1;
|
||||
|
||||
value_end = value_start;
|
||||
|
||||
while ((value_end < qs_end) && !is_param_delimiter(*value_end, delim))
|
||||
@ -11574,8 +11580,12 @@ smp_fetch_url_param(const struct arg *args, struct sample *smp, const char *kw,
|
||||
{
|
||||
char delim = '?';
|
||||
struct http_msg *msg;
|
||||
char *query_string, *qs_end;
|
||||
const char *name;
|
||||
int name_len;
|
||||
|
||||
if (!args || args[0].type != ARGT_STR ||
|
||||
if (!args ||
|
||||
(args[0].type && args[0].type != ARGT_STR) ||
|
||||
(args[1].type && args[1].type != ARGT_STR))
|
||||
return 0;
|
||||
|
||||
@ -11586,14 +11596,42 @@ smp_fetch_url_param(const struct arg *args, struct sample *smp, const char *kw,
|
||||
if (args[1].type)
|
||||
delim = *args[1].data.str.str;
|
||||
|
||||
if (!find_url_param_value(msg->chn->buf->p + msg->sl.rq.u, msg->sl.rq.u_l,
|
||||
args->data.str.str, args->data.str.len,
|
||||
query_string = smp->ctx.a[0];
|
||||
qs_end = smp->ctx.a[1];
|
||||
|
||||
if (!query_string) { // first call, find the query string
|
||||
query_string = find_param_list(msg->chn->buf->p + msg->sl.rq.u,
|
||||
msg->sl.rq.u_l, delim);
|
||||
if (!query_string)
|
||||
return 0;
|
||||
|
||||
qs_end = msg->chn->buf->p + msg->sl.rq.u + msg->sl.rq.u_l;
|
||||
smp->ctx.a[0] = query_string;
|
||||
smp->ctx.a[1] = qs_end;
|
||||
}
|
||||
|
||||
name = "";
|
||||
name_len = 0;
|
||||
if (args->type == ARGT_STR) {
|
||||
name = args->data.str.str;
|
||||
name_len = args->data.str.len;
|
||||
}
|
||||
|
||||
if (!find_next_url_param(query_string, qs_end,
|
||||
name, name_len,
|
||||
&smp->data.str.str, &smp->data.str.len,
|
||||
delim))
|
||||
return 0;
|
||||
|
||||
query_string = smp->data.str.str + smp->data.str.len + 1;
|
||||
smp->ctx.a[0] = query_string;
|
||||
|
||||
smp->type = SMP_T_STR;
|
||||
smp->flags = SMP_F_VOL_1ST | SMP_F_CONST;
|
||||
|
||||
if (query_string < qs_end)
|
||||
smp->flags |= SMP_F_NOT_LAST;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -12466,9 +12504,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_UINT, SMP_USE_HRQHV },
|
||||
{ "url_param", smp_fetch_url_param, ARG2(1,STR,STR), NULL, SMP_T_STR, SMP_USE_HRQHV },
|
||||
{ "urlp" , smp_fetch_url_param, ARG2(1,STR,STR), NULL, SMP_T_STR, SMP_USE_HRQHV },
|
||||
{ "urlp_val", smp_fetch_url_param_val, ARG2(1,STR,STR), NULL, SMP_T_UINT, 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_UINT, SMP_USE_HRQHV },
|
||||
{ /* END */ },
|
||||
}};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user