mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-25 12:28:01 +00:00
MEDIUM: capture: adds http-response capture
This patch adds a http response capture keyword with the same behavior as the previous patch called "MEDIUM: capture: Allow capture with slot identifier".
This commit is contained in:
parent
cdb67cad01
commit
e80fadaaca
@ -3612,6 +3612,7 @@ http-request { allow | deny | tarpit | auth [realm <realm>] | redirect <rule> |
|
|||||||
about ACL usage.
|
about ACL usage.
|
||||||
|
|
||||||
http-response { allow | deny | add-header <name> <fmt> | set-nice <nice> |
|
http-response { allow | deny | add-header <name> <fmt> | set-nice <nice> |
|
||||||
|
capture <sample> id <id> |
|
||||||
set-header <name> <fmt> | del-header <name> |
|
set-header <name> <fmt> | del-header <name> |
|
||||||
replace-header <name> <regex-match> <replace-fmt> |
|
replace-header <name> <regex-match> <replace-fmt> |
|
||||||
replace-value <name> <regex-match> <replace-fmt> |
|
replace-value <name> <regex-match> <replace-fmt> |
|
||||||
@ -3772,6 +3773,21 @@ http-response { allow | deny | add-header <name> <fmt> | set-nice <nice> |
|
|||||||
parameter is the name of the function to run. The prototype of the
|
parameter is the name of the function to run. The prototype of the
|
||||||
function is documented in the API documentation.
|
function is documented in the API documentation.
|
||||||
|
|
||||||
|
- capture <sample> id <id> :
|
||||||
|
captures sample expression <sample> from the response buffer, and converts
|
||||||
|
it to a string. The resulting string is stored into the next request
|
||||||
|
"capture" slot, so it will possibly appear next to some captured HTTP
|
||||||
|
headers. It will then automatically appear in the logs, and it will be
|
||||||
|
possible to extract it using sample fetch rules to feed it into headers or
|
||||||
|
anything. Please check section 7.3 (Fetching samples) and "capture
|
||||||
|
response header" for more information.
|
||||||
|
|
||||||
|
The keyword "id" is the id of the capture slot which is used for storing
|
||||||
|
the string. The capture slot must be defined in an associated frontend.
|
||||||
|
This is useful to run captures in backends. The slot id can be declared by
|
||||||
|
a previous directive "http-response capture" or with the "declare capture"
|
||||||
|
keyword.
|
||||||
|
|
||||||
There is no limit to the number of http-response statements per instance.
|
There is no limit to the number of http-response statements per instance.
|
||||||
|
|
||||||
It is important to know that http-response rules are processed very early in
|
It is important to know that http-response rules are processed very early in
|
||||||
|
127
src/proto_http.c
127
src/proto_http.c
@ -12633,6 +12633,124 @@ int parse_http_req_capture(const char **args, int *orig_arg, struct proxy *px, s
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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_res_capture_by_id(struct http_res_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->res_cap;
|
||||||
|
struct proxy *fe = strm_fe(s);
|
||||||
|
int len;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Look for the original configuration. */
|
||||||
|
for (h = fe->rsp_cap, i = fe->nb_rsp_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_RES|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-response 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 od the preallocated id into arg->act.p[1].
|
||||||
|
* It returns 0 on success, < 0 on error.
|
||||||
|
*/
|
||||||
|
int parse_http_res_capture(const char **args, int *orig_arg, struct proxy *px, struct http_res_rule *rule, char **err)
|
||||||
|
{
|
||||||
|
struct sample_expr *expr;
|
||||||
|
int cur_arg;
|
||||||
|
int id;
|
||||||
|
char *error;
|
||||||
|
|
||||||
|
for (cur_arg = *orig_arg; cur_arg < *orig_arg + 3 && *args[cur_arg]; cur_arg++)
|
||||||
|
if (strcmp(args[cur_arg], "if") == 0 ||
|
||||||
|
strcmp(args[cur_arg], "unless") == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (cur_arg < *orig_arg + 3) {
|
||||||
|
memprintf(err, "expects <expression> [ 'len' <length> | id <idx> ]");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!(expr->fetch->val & SMP_VAL_FE_HRS_HDR)) {
|
||||||
|
memprintf(err,
|
||||||
|
"fetch method '%s' extracts information from '%s', none of which is available here",
|
||||||
|
args[cur_arg-1], sample_src_names(expr->fetch->use));
|
||||||
|
free(expr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!args[cur_arg] || !*args[cur_arg]) {
|
||||||
|
memprintf(err, "expects 'len or 'id'");
|
||||||
|
free(expr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(args[cur_arg], "id") != 0) {
|
||||||
|
memprintf(err, "expects 'id', found '%s'", args[cur_arg]);
|
||||||
|
free(expr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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++;
|
||||||
|
|
||||||
|
LIST_INIT((struct list *)&rule->arg.act.p[0]);
|
||||||
|
proxy->conf.args.ctx = ARGC_CAP;
|
||||||
|
|
||||||
|
rule->action = HTTP_RES_ACT_CUSTOM_CONT;
|
||||||
|
rule->action_ptr = http_action_res_capture_by_id;
|
||||||
|
rule->arg.act.p[0] = expr;
|
||||||
|
rule->arg.act.p[1] = (void *)(long)id;
|
||||||
|
|
||||||
|
*orig_arg = cur_arg;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the struct http_req_action_kw associated to a keyword.
|
* Return the struct http_req_action_kw associated to a keyword.
|
||||||
*/
|
*/
|
||||||
@ -12908,6 +13026,14 @@ struct http_req_action_kw_list http_req_actions = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct http_res_action_kw_list http_res_actions = {
|
||||||
|
.scope = "http",
|
||||||
|
.kw = {
|
||||||
|
{ "capture", parse_http_res_capture },
|
||||||
|
{ NULL, NULL }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
__attribute__((constructor))
|
__attribute__((constructor))
|
||||||
static void __http_protocol_init(void)
|
static void __http_protocol_init(void)
|
||||||
{
|
{
|
||||||
@ -12915,6 +13041,7 @@ static void __http_protocol_init(void)
|
|||||||
sample_register_fetches(&sample_fetch_keywords);
|
sample_register_fetches(&sample_fetch_keywords);
|
||||||
sample_register_convs(&sample_conv_kws);
|
sample_register_convs(&sample_conv_kws);
|
||||||
http_req_keywords_register(&http_req_actions);
|
http_req_keywords_register(&http_req_actions);
|
||||||
|
http_res_keywords_register(&http_res_actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user