mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-07 14:01:54 +00:00
MEDIUM: capture: Allow capture with slot identifier
This patch modifies the current http-request capture function and adds a new keyword "id" that permits to identify a capture slot. If the identified doesn't exists, the action fails silently. Note that this patch removs an unused list initilisation, which seems to be inherited from a copy/paste. It's harmless and does not need to be backported. LIST_INIT((struct list *)&rule->arg.act.p[0]);
This commit is contained in:
parent
35ab27561e
commit
82bf70dff4
@ -3278,7 +3278,7 @@ http-check send-state
|
|||||||
|
|
||||||
http-request { allow | deny | tarpit | auth [realm <realm>] | redirect <rule> |
|
http-request { allow | deny | tarpit | auth [realm <realm>] | redirect <rule> |
|
||||||
add-header <name> <fmt> | set-header <name> <fmt> |
|
add-header <name> <fmt> | set-header <name> <fmt> |
|
||||||
capture <sample> len <length> |
|
capture <sample> [ len <length> | id <id> ] |
|
||||||
del-header <name> | set-nice <nice> | set-log-level <level> |
|
del-header <name> | set-nice <nice> | set-log-level <level> |
|
||||||
replace-header <name> <match-regex> <replace-fmt> |
|
replace-header <name> <match-regex> <replace-fmt> |
|
||||||
replace-value <name> <match-regex> <replace-fmt> |
|
replace-value <name> <match-regex> <replace-fmt> |
|
||||||
@ -3497,7 +3497,7 @@ http-request { allow | deny | tarpit | auth [realm <realm>] | redirect <rule> |
|
|||||||
with large lists! It is the equivalent of the "set map" command from the
|
with large lists! It is the equivalent of the "set map" command from the
|
||||||
stats socket, but can be triggered by an HTTP request.
|
stats socket, but can be triggered by an HTTP request.
|
||||||
|
|
||||||
- capture <sample> len <length> :
|
- capture <sample> [ len <length> | id <id> ] :
|
||||||
captures sample expression <sample> from the request buffer, and converts
|
captures sample expression <sample> from the request buffer, and converts
|
||||||
it to a string of at most <len> characters. The resulting string is
|
it to a string of at most <len> characters. The resulting string is
|
||||||
stored into the next request "capture" slot, so it will possibly appear
|
stored into the next request "capture" slot, so it will possibly appear
|
||||||
@ -3508,6 +3508,11 @@ http-request { allow | deny | tarpit | auth [realm <realm>] | redirect <rule> |
|
|||||||
session life. Please check section 7.3 (Fetching samples) and "capture
|
session life. Please check section 7.3 (Fetching samples) and "capture
|
||||||
request header" for more information.
|
request header" for more information.
|
||||||
|
|
||||||
|
If the keyword "id" is used instead of "len", the action tries to store
|
||||||
|
the captured string in a previously declared capture slot. This is useful
|
||||||
|
to run captures in backends. The slot id can be declared by a previous
|
||||||
|
directive "http-request capture" or with the "declare capture" keyword.
|
||||||
|
|
||||||
- { track-sc0 | track-sc1 | track-sc2 } <key> [table <table>] :
|
- { track-sc0 | track-sc1 | track-sc2 } <key> [table <table>] :
|
||||||
enables tracking of sticky counters from current request. These rules
|
enables tracking of sticky counters from current request. These rules
|
||||||
do not stop evaluation and do not change default action. Three sets of
|
do not stop evaluation and do not change default action. Three sets of
|
||||||
|
140
src/proto_http.c
140
src/proto_http.c
@ -12464,9 +12464,52 @@ int http_action_req_capture(struct http_req_rule *rule, struct proxy *px, struct
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This function executes the "capture" action and store the result in a
|
||||||
|
* capture slot if exists. It executes a fetch expression, turns the result
|
||||||
|
* into a string and puts it in a capture slot. It always returns 1. If an
|
||||||
|
* error occurs the action is cancelled, but the rule processing continues.
|
||||||
|
*/
|
||||||
|
int http_action_req_capture_by_id(struct http_req_rule *rule, struct proxy *px, struct stream *s)
|
||||||
|
{
|
||||||
|
struct session *sess = s->sess;
|
||||||
|
struct sample *key;
|
||||||
|
struct sample_expr *expr = rule->arg.act.p[0];
|
||||||
|
struct cap_hdr *h;
|
||||||
|
int idx = (long)rule->arg.act.p[1];
|
||||||
|
char **cap = s->req_cap;
|
||||||
|
struct proxy *fe = strm_fe(s);
|
||||||
|
int len;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Look for the original configuration. */
|
||||||
|
for (h = fe->req_cap, i = fe->nb_req_cap - 1;
|
||||||
|
h != NULL && i != idx ;
|
||||||
|
i--, h = h->next);
|
||||||
|
if (!h)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
key = sample_fetch_string(s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, expr);
|
||||||
|
if (!key)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (cap[h->index] == NULL)
|
||||||
|
cap[h->index] = pool_alloc2(h->pool);
|
||||||
|
|
||||||
|
if (cap[h->index] == NULL) /* no more capture memory */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
len = key->data.str.len;
|
||||||
|
if (len > h->len)
|
||||||
|
len = h->len;
|
||||||
|
|
||||||
|
memcpy(cap[h->index], key->data.str.str, len);
|
||||||
|
cap[h->index][len] = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* parse an "http-request capture" action. It takes a single argument which is
|
/* parse an "http-request capture" action. It takes a single argument which is
|
||||||
* a sample fetch expression. It stores the expression into arg->act.p[0] and
|
* a sample fetch expression. It stores the expression into arg->act.p[0] and
|
||||||
* the allocated hdr_cap struct into arg->act.p[1].
|
* the allocated hdr_cap struct or the preallocated "id" into arg->act.p[1].
|
||||||
* It returns 0 on success, < 0 on error.
|
* It returns 0 on success, < 0 on error.
|
||||||
*/
|
*/
|
||||||
int parse_http_req_capture(const char **args, int *orig_arg, struct proxy *px, struct http_req_rule *rule, char **err)
|
int parse_http_req_capture(const char **args, int *orig_arg, struct proxy *px, struct http_req_rule *rule, char **err)
|
||||||
@ -12482,18 +12525,10 @@ int parse_http_req_capture(const char **args, int *orig_arg, struct proxy *px, s
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (cur_arg < *orig_arg + 3) {
|
if (cur_arg < *orig_arg + 3) {
|
||||||
memprintf(err, "expects <expression> 'len' <length> ");
|
memprintf(err, "expects <expression> [ 'len' <length> | id <idx> ]");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(px->cap & PR_CAP_FE)) {
|
|
||||||
memprintf(err, "proxy '%s' has no frontend capability", px->id);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
LIST_INIT((struct list *)&rule->arg.act.p[0]);
|
|
||||||
proxy->conf.args.ctx = ARGC_CAP;
|
|
||||||
|
|
||||||
cur_arg = *orig_arg;
|
cur_arg = *orig_arg;
|
||||||
expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args);
|
expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args);
|
||||||
if (!expr)
|
if (!expr)
|
||||||
@ -12507,8 +12542,22 @@ int parse_http_req_capture(const char **args, int *orig_arg, struct proxy *px, s
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!args[cur_arg] || !*args[cur_arg]) {
|
||||||
|
memprintf(err, "expects 'len or 'id'");
|
||||||
|
free(expr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(args[cur_arg], "len") == 0) {
|
if (strcmp(args[cur_arg], "len") == 0) {
|
||||||
cur_arg++;
|
cur_arg++;
|
||||||
|
|
||||||
|
if (!(px->cap & PR_CAP_FE)) {
|
||||||
|
memprintf(err, "proxy '%s' has no frontend capability", px->id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy->conf.args.ctx = ARGC_CAP;
|
||||||
|
|
||||||
if (!args[cur_arg]) {
|
if (!args[cur_arg]) {
|
||||||
memprintf(err, "missing length value");
|
memprintf(err, "missing length value");
|
||||||
free(expr);
|
free(expr);
|
||||||
@ -12522,31 +12571,64 @@ int parse_http_req_capture(const char **args, int *orig_arg, struct proxy *px, s
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
cur_arg++;
|
cur_arg++;
|
||||||
|
|
||||||
|
if (!len) {
|
||||||
|
memprintf(err, "a positive 'len' argument is mandatory");
|
||||||
|
free(expr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hdr = calloc(sizeof(struct cap_hdr), 1);
|
||||||
|
hdr->next = px->req_cap;
|
||||||
|
hdr->name = NULL; /* not a header capture */
|
||||||
|
hdr->namelen = 0;
|
||||||
|
hdr->len = len;
|
||||||
|
hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
|
||||||
|
hdr->index = px->nb_req_cap++;
|
||||||
|
|
||||||
|
px->req_cap = hdr;
|
||||||
|
px->to_log |= LW_REQHDR;
|
||||||
|
|
||||||
|
rule->action = HTTP_REQ_ACT_CUSTOM_CONT;
|
||||||
|
rule->action_ptr = http_action_req_capture;
|
||||||
|
rule->arg.act.p[0] = expr;
|
||||||
|
rule->arg.act.p[1] = hdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!len) {
|
else if (strcmp(args[cur_arg], "id") == 0) {
|
||||||
memprintf(err, "a positive 'len' argument is mandatory");
|
int id;
|
||||||
|
char *error;
|
||||||
|
|
||||||
|
cur_arg++;
|
||||||
|
|
||||||
|
if (!args[cur_arg]) {
|
||||||
|
memprintf(err, "missing id value");
|
||||||
|
free(expr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
id = strtol(args[cur_arg], &error, 10);
|
||||||
|
if (*error != '\0') {
|
||||||
|
memprintf(err, "cannot parse id '%s'", args[cur_arg]);
|
||||||
|
free(expr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cur_arg++;
|
||||||
|
|
||||||
|
proxy->conf.args.ctx = ARGC_CAP;
|
||||||
|
|
||||||
|
rule->action = HTTP_REQ_ACT_CUSTOM_CONT;
|
||||||
|
rule->action_ptr = http_action_req_capture_by_id;
|
||||||
|
rule->arg.act.p[0] = expr;
|
||||||
|
rule->arg.act.p[1] = (void *)(long)id;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
memprintf(err, "expects 'len' or 'id', found '%s'", args[cur_arg]);
|
||||||
free(expr);
|
free(expr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
hdr = calloc(sizeof(struct cap_hdr), 1);
|
|
||||||
hdr->next = px->req_cap;
|
|
||||||
hdr->name = NULL; /* not a header capture */
|
|
||||||
hdr->namelen = 0;
|
|
||||||
hdr->len = len;
|
|
||||||
hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
|
|
||||||
hdr->index = px->nb_req_cap++;
|
|
||||||
|
|
||||||
px->req_cap = hdr;
|
|
||||||
px->to_log |= LW_REQHDR;
|
|
||||||
|
|
||||||
rule->action = HTTP_REQ_ACT_CUSTOM_CONT;
|
|
||||||
rule->action_ptr = http_action_req_capture;
|
|
||||||
rule->arg.act.p[0] = expr;
|
|
||||||
rule->arg.act.p[1] = hdr;
|
|
||||||
|
|
||||||
*orig_arg = cur_arg;
|
*orig_arg = cur_arg;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user