mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-21 13:16:57 +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
|
restrict access to certain systems through a proxy, for example when combined
|
||||||
with option "http_proxy".
|
with option "http_proxy".
|
||||||
|
|
||||||
urlp(<name>[,<delim>]) : string
|
urlp([<name>[,<delim>]]) : string
|
||||||
url_param(<name>[,<delim>]) : string
|
url_param([<name>[,<delim>]]) : 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. The result is a string
|
';' or <delim>. The parameter name is case-sensitive. If no name is given,
|
||||||
corresponding to the value of the parameter <name> as presented in the
|
any parameter will match, and the first one will be returned. The result is
|
||||||
request (no URL decoding is performed). This can be used for session
|
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
|
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
|
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
|
this fetch iterates over multiple parameters and will iteratively report all
|
||||||
as well.
|
parameters values if no name is given
|
||||||
|
|
||||||
ACL derivatives :
|
ACL derivatives :
|
||||||
urlp(<name>[,<delim>]) : exact string match
|
urlp(<name>[,<delim>]) : exact string match
|
||||||
@ -12738,7 +12739,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>])] : 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.
|
||||||
|
@ -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:
|
* 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)
|
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*
|
static char*
|
||||||
find_url_param_pos(char* query_string, size_t query_string_l,
|
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 delim)
|
||||||
{
|
{
|
||||||
char *pos, *last;
|
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
|
* Given a url parameter name and a query string, returns its value and size
|
||||||
* *value_l respectively, and returns non-zero. If the parameter is not found,
|
* into *value and *value_l respectively, and returns non-zero. An empty
|
||||||
* zero is returned and value/value_l are not touched.
|
* 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
|
static int
|
||||||
find_url_param_value(char* path, size_t path_l,
|
find_next_url_param(char* query_string, char *qs_end,
|
||||||
char* url_param_name, size_t url_param_name_l,
|
const char* url_param_name, size_t url_param_name_l,
|
||||||
char** value, int* value_l, char delim)
|
char** value, int* value_l, char delim)
|
||||||
{
|
{
|
||||||
char *query_string, *qs_end;
|
|
||||||
char *arg_start;
|
char *arg_start;
|
||||||
char *value_start, *value_end;
|
char *value_start, *value_end;
|
||||||
|
|
||||||
query_string = find_param_list(path, path_l, delim);
|
arg_start = query_string;
|
||||||
if (!query_string)
|
if (url_param_name_l) {
|
||||||
return 0;
|
arg_start = find_url_param_pos(query_string, qs_end - query_string,
|
||||||
|
url_param_name, url_param_name_l,
|
||||||
qs_end = path + path_l;
|
delim);
|
||||||
arg_start = find_url_param_pos(query_string, qs_end - query_string,
|
}
|
||||||
url_param_name, url_param_name_l,
|
|
||||||
delim);
|
|
||||||
if (!arg_start)
|
if (!arg_start)
|
||||||
return 0;
|
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;
|
value_end = value_start;
|
||||||
|
|
||||||
while ((value_end < qs_end) && !is_param_delimiter(*value_end, delim))
|
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 = '?';
|
char delim = '?';
|
||||||
struct http_msg *msg;
|
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))
|
(args[1].type && args[1].type != ARGT_STR))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -11586,14 +11596,42 @@ smp_fetch_url_param(const struct arg *args, struct sample *smp, const char *kw,
|
|||||||
if (args[1].type)
|
if (args[1].type)
|
||||||
delim = *args[1].data.str.str;
|
delim = *args[1].data.str.str;
|
||||||
|
|
||||||
if (!find_url_param_value(msg->chn->buf->p + msg->sl.rq.u, msg->sl.rq.u_l,
|
query_string = smp->ctx.a[0];
|
||||||
args->data.str.str, args->data.str.len,
|
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,
|
&smp->data.str.str, &smp->data.str.len,
|
||||||
delim))
|
delim))
|
||||||
return 0;
|
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->type = SMP_T_STR;
|
||||||
smp->flags = SMP_F_VOL_1ST | SMP_F_CONST;
|
smp->flags = SMP_F_VOL_1ST | SMP_F_CONST;
|
||||||
|
|
||||||
|
if (query_string < qs_end)
|
||||||
|
smp->flags |= SMP_F_NOT_LAST;
|
||||||
|
|
||||||
return 1;
|
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 },
|
{ "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_UINT, 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 },
|
{ "url_param", smp_fetch_url_param, ARG2(0,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" , smp_fetch_url_param, ARG2(0,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 },
|
{ "urlp_val", smp_fetch_url_param_val, ARG2(0,STR,STR), NULL, SMP_T_UINT, SMP_USE_HRQHV },
|
||||||
{ /* END */ },
|
{ /* END */ },
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user