mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-31 18:41:39 +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> |
|
||||
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> |
|
||||
replace-header <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
|
||||
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
|
||||
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
|
||||
@ -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
|
||||
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>] :
|
||||
enables tracking of sticky counters from current request. These rules
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
|
||||
if (cur_arg < *orig_arg + 3) {
|
||||
memprintf(err, "expects <expression> 'len' <length> ");
|
||||
memprintf(err, "expects <expression> [ 'len' <length> | id <idx> ]");
|
||||
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;
|
||||
expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args);
|
||||
if (!expr)
|
||||
@ -12507,8 +12542,22 @@ int parse_http_req_capture(const char **args, int *orig_arg, struct proxy *px, s
|
||||
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) {
|
||||
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]) {
|
||||
memprintf(err, "missing length value");
|
||||
free(expr);
|
||||
@ -12522,31 +12571,64 @@ int parse_http_req_capture(const char **args, int *orig_arg, struct proxy *px, s
|
||||
return -1;
|
||||
}
|
||||
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) {
|
||||
memprintf(err, "a positive 'len' argument is mandatory");
|
||||
else if (strcmp(args[cur_arg], "id") == 0) {
|
||||
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);
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user