mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-08 08:07:10 +02:00
MINOR: http-rules: Make set-header and add-header custom actions
Now, these actions use their own dedicated function and are no longer handled "in place" during the HTTP rules evaluation. Thus the action names ACT_HTTP_SET_HDR and ACT_HTTP_ADD_VAL are removed. The action type is now set to 0 to set a header (so remove existing ones if any and add a new one) or to 1 to add a header (add without remove).
This commit is contained in:
parent
92d34fe38d
commit
d1f27e3394
@ -78,8 +78,6 @@ enum act_name {
|
|||||||
ACT_ACTION_DENY,
|
ACT_ACTION_DENY,
|
||||||
|
|
||||||
/* common http actions .*/
|
/* common http actions .*/
|
||||||
ACT_HTTP_ADD_HDR,
|
|
||||||
ACT_HTTP_SET_HDR,
|
|
||||||
ACT_HTTP_DEL_HDR,
|
ACT_HTTP_DEL_HDR,
|
||||||
ACT_HTTP_REDIR,
|
ACT_HTTP_REDIR,
|
||||||
ACT_HTTP_SET_NICE,
|
ACT_HTTP_SET_NICE,
|
||||||
|
@ -943,6 +943,66 @@ static enum act_parse_ret parse_http_set_log_level(const char **args, int *orig_
|
|||||||
return ACT_RET_PRS_OK;
|
return ACT_RET_PRS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This function executes a set-header or add-header actions. It builds a string
|
||||||
|
* in the trash from the specified format string. It finds the action to be
|
||||||
|
* performed in <.action>, previously filled by function parse_set_header(). The
|
||||||
|
* replacement action is excuted by the function http_action_set_header(). On
|
||||||
|
* success, it returns ACT_RET_CONT. If an error occurs while soft rewrites are
|
||||||
|
* enabled, the action is canceled, but the rule processing continue. Otherwsize
|
||||||
|
* ACT_RET_ERR is returned.
|
||||||
|
*/
|
||||||
|
static enum act_return http_action_set_header(struct act_rule *rule, struct proxy *px,
|
||||||
|
struct session *sess, struct stream *s, int flags)
|
||||||
|
{
|
||||||
|
struct htx *htx = htxbuf((rule->from == ACT_F_HTTP_REQ) ? &s->req.buf : &s->res.buf);
|
||||||
|
enum act_return ret = ACT_RET_CONT;
|
||||||
|
struct buffer *replace;
|
||||||
|
struct http_hdr_ctx ctx;
|
||||||
|
struct ist n, v;
|
||||||
|
|
||||||
|
replace = alloc_trash_chunk();
|
||||||
|
if (!replace)
|
||||||
|
goto fail_alloc;
|
||||||
|
|
||||||
|
replace->data = build_logline(s, replace->area, replace->size, &rule->arg.http.fmt);
|
||||||
|
n = rule->arg.http.str;
|
||||||
|
v = ist2(replace->area, replace->data);
|
||||||
|
|
||||||
|
if (rule->action == 0) { // set-header
|
||||||
|
/* remove all occurrences of the header */
|
||||||
|
ctx.blk = NULL;
|
||||||
|
while (http_find_header(htx, n, &ctx, 1))
|
||||||
|
http_remove_header(htx, &ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now add header */
|
||||||
|
if (!http_add_header(htx, n, v))
|
||||||
|
goto fail_rewrite;
|
||||||
|
|
||||||
|
leave:
|
||||||
|
free_trash_chunk(replace);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
fail_alloc:
|
||||||
|
if (!(s->flags & SF_ERR_MASK))
|
||||||
|
s->flags |= SF_ERR_RESOURCE;
|
||||||
|
ret = ACT_RET_ERR;
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
fail_rewrite:
|
||||||
|
_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_rewrites, 1);
|
||||||
|
if (s->flags & SF_BE_ASSIGNED)
|
||||||
|
_HA_ATOMIC_ADD(&s->be->be_counters.failed_rewrites, 1);
|
||||||
|
if (sess->listener->counters)
|
||||||
|
_HA_ATOMIC_ADD(&sess->listener->counters->failed_rewrites, 1);
|
||||||
|
if (objt_server(s->target))
|
||||||
|
_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.failed_rewrites, 1);
|
||||||
|
|
||||||
|
if (!(s->txn->req.flags & HTTP_MSGF_SOFT_RW))
|
||||||
|
ret = ACT_RET_ERR;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse a "set-header", "add-header" or "early-hint" actions. It takes an
|
/* Parse a "set-header", "add-header" or "early-hint" actions. It takes an
|
||||||
* header name and a log-format string as arguments. It returns ACT_RET_PRS_OK
|
* header name and a log-format string as arguments. It returns ACT_RET_PRS_OK
|
||||||
* on success, ACT_RET_PRS_ERR on error.
|
* on success, ACT_RET_PRS_ERR on error.
|
||||||
@ -955,8 +1015,15 @@ static enum act_parse_ret parse_http_set_header(const char **args, int *orig_arg
|
|||||||
{
|
{
|
||||||
int cap, cur_arg;
|
int cap, cur_arg;
|
||||||
|
|
||||||
rule->action = (*args[*orig_arg-1] == 'a' ? ACT_HTTP_ADD_HDR :
|
if (args[*orig_arg-1][0] == 'e')
|
||||||
*args[*orig_arg-1] == 's' ? ACT_HTTP_SET_HDR : ACT_HTTP_EARLY_HINT);
|
rule->action = ACT_HTTP_EARLY_HINT;
|
||||||
|
else {
|
||||||
|
if (args[*orig_arg-1][0] == 's')
|
||||||
|
rule->action = 0; // set-header
|
||||||
|
else
|
||||||
|
rule->action = 1; // add-header
|
||||||
|
rule->action_ptr = http_action_set_header;
|
||||||
|
}
|
||||||
|
|
||||||
cur_arg = *orig_arg;
|
cur_arg = *orig_arg;
|
||||||
if (!*args[cur_arg] || !*args[cur_arg+1]) {
|
if (!*args[cur_arg] || !*args[cur_arg+1]) {
|
||||||
|
@ -3038,52 +3038,6 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
|
|||||||
http_remove_header(htx, &ctx);
|
http_remove_header(htx, &ctx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACT_HTTP_SET_HDR:
|
|
||||||
case ACT_HTTP_ADD_HDR: {
|
|
||||||
/* The scope of the trash buffer must be limited to this function. The
|
|
||||||
* build_logline() function can execute a lot of other function which
|
|
||||||
* can use the trash buffer. So for limiting the scope of this global
|
|
||||||
* buffer, we build first the header value using build_logline, and
|
|
||||||
* after we store the header name.
|
|
||||||
*/
|
|
||||||
struct buffer *replace;
|
|
||||||
struct ist n, v;
|
|
||||||
|
|
||||||
replace = alloc_trash_chunk();
|
|
||||||
if (!replace) {
|
|
||||||
if (!(s->flags & SF_ERR_MASK))
|
|
||||||
s->flags |= SF_ERR_RESOURCE;
|
|
||||||
rule_ret = HTTP_RULE_RES_ERROR;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
replace->data = build_logline(s, replace->area, replace->size, &rule->arg.http.fmt);
|
|
||||||
n = rule->arg.http.str;
|
|
||||||
v = ist2(replace->area, replace->data);
|
|
||||||
|
|
||||||
if (rule->action == ACT_HTTP_SET_HDR) {
|
|
||||||
/* remove all occurrences of the header */
|
|
||||||
ctx.blk = NULL;
|
|
||||||
while (http_find_header(htx, n, &ctx, 1))
|
|
||||||
http_remove_header(htx, &ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!http_add_header(htx, n, v)) {
|
|
||||||
_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_rewrites, 1);
|
|
||||||
if (s->flags & SF_BE_ASSIGNED)
|
|
||||||
_HA_ATOMIC_ADD(&s->be->be_counters.failed_rewrites, 1);
|
|
||||||
if (sess->listener->counters)
|
|
||||||
_HA_ATOMIC_ADD(&sess->listener->counters->failed_rewrites, 1);
|
|
||||||
|
|
||||||
if (!(txn->req.flags & HTTP_MSGF_SOFT_RW)) {
|
|
||||||
rule_ret = HTTP_RULE_RES_ERROR;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free_trash_chunk(replace);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ACT_HTTP_DEL_ACL:
|
case ACT_HTTP_DEL_ACL:
|
||||||
case ACT_HTTP_DEL_MAP: {
|
case ACT_HTTP_DEL_MAP: {
|
||||||
struct pat_ref *ref;
|
struct pat_ref *ref;
|
||||||
@ -3400,47 +3354,6 @@ static enum rule_result http_res_get_intercept_rule(struct proxy *px, struct lis
|
|||||||
http_remove_header(htx, &ctx);
|
http_remove_header(htx, &ctx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACT_HTTP_SET_HDR:
|
|
||||||
case ACT_HTTP_ADD_HDR: {
|
|
||||||
struct buffer *replace;
|
|
||||||
struct ist n, v;
|
|
||||||
|
|
||||||
replace = alloc_trash_chunk();
|
|
||||||
if (!replace) {
|
|
||||||
if (!(s->flags & SF_ERR_MASK))
|
|
||||||
s->flags |= SF_ERR_RESOURCE;
|
|
||||||
rule_ret = HTTP_RULE_RES_ERROR;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
replace->data = build_logline(s, replace->area, replace->size, &rule->arg.http.fmt);
|
|
||||||
n = rule->arg.http.str;
|
|
||||||
v = ist2(replace->area, replace->data);
|
|
||||||
|
|
||||||
if (rule->action == ACT_HTTP_SET_HDR) {
|
|
||||||
/* remove all occurrences of the header */
|
|
||||||
ctx.blk = NULL;
|
|
||||||
while (http_find_header(htx, n, &ctx, 1))
|
|
||||||
http_remove_header(htx, &ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!http_add_header(htx, n, v)) {
|
|
||||||
_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_rewrites, 1);
|
|
||||||
_HA_ATOMIC_ADD(&s->be->be_counters.failed_rewrites, 1);
|
|
||||||
if (sess->listener->counters)
|
|
||||||
_HA_ATOMIC_ADD(&sess->listener->counters->failed_rewrites, 1);
|
|
||||||
if (objt_server(s->target))
|
|
||||||
_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.failed_rewrites, 1);
|
|
||||||
|
|
||||||
if (!(txn->rsp.flags & HTTP_MSGF_SOFT_RW)) {
|
|
||||||
rule_ret = HTTP_RULE_RES_ERROR;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free_trash_chunk(replace);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ACT_HTTP_DEL_ACL:
|
case ACT_HTTP_DEL_ACL:
|
||||||
case ACT_HTTP_DEL_MAP: {
|
case ACT_HTTP_DEL_MAP: {
|
||||||
struct pat_ref *ref;
|
struct pat_ref *ref;
|
||||||
|
Loading…
Reference in New Issue
Block a user