MEDIUM: streams: Add a new http action, disable-l7-retry.

Add a new action for http-request, disable-l7-retry, that can be used to
disable any attempt at retry requests (see retry-on) if it fails for any
reason other than a connection failure.
This is useful for example to make sure POST requests aren't retried.
This commit is contained in:
Olivier Houchard 2019-05-10 13:59:15 +02:00 committed by Olivier Houchard
parent ad26d8d820
commit 602bf7d2ea
4 changed files with 41 additions and 1 deletions

View File

@ -4297,6 +4297,11 @@ http-request deny [deny_status <status>] [ { if | unless } <condition> ]
those that can be overridden by the "errorfile" directive.
No further "http-request" rules are evaluated.
http-request disable-l7-retry [ { if | unless } <condition> ]
This disables any attempt to retry the request if it fails for any other
reason than a connection failure. This can be useful for example to make
sure POST requests aren't retried on failure.
http-request do-resolve(<var>,<resolvers>,[ipv4,ipv6]) <expr> :
This action performs a DNS resolution of the output of <expr> and stores

View File

@ -84,6 +84,7 @@ enum {
SI_FL_RXBLK_ANY = 0x001F0000, /* any of the RXBLK flags above */
SI_FL_RX_WAIT_EP = 0x00200000, /* stream-int waits for more data from the end point */
SI_FL_L7_RETRY = 0x01000000, /* The stream interface may attempt L7 retries */
SI_FL_D_L7_RETRY = 0x02000000, /* Disable L7 retries on this stream interface, even if configured to do it */
};
/* A stream interface has 3 parts :

View File

@ -217,6 +217,38 @@ static enum act_parse_ret parse_http_action_reject(const char **args, int *orig_
return ACT_RET_PRS_OK;
}
/* This function executes the "disable-l7-retry" HTTP action.
* It disables L7 retries (all retry except for a connection failure). This
* can be useful for example to avoid retrying on POST requests.
* It just removes the L7 retry flag on the stream_interface, and always
* return ACT_RET_CONT;
*/
static enum act_return http_req_disable_l7_retry(struct act_rule *rule, struct proxy *px,
struct session *sess, struct stream *s, int flags)
{
struct stream_interface *si = &s->si[1];
/* In theory, the SI_FL_L7_RETRY flags isn't set at this point, but
* let's be future-proof and remove it anyway.
*/
si->flags &= ~SI_FL_L7_RETRY;
si->flags |= SI_FL_D_L7_RETRY;
return ACT_RET_CONT;
}
/* parse the "disable-l7-retry" action:
* This action takes no argument and returns ACT_RET_PRS_OK on success,
* ACT_RET_PRS_ERR on error.
*/
static enum act_parse_ret parse_http_req_disable_l7_retry(const char **args,
int *orig_args, struct proxy *px,
struct act_rule *rule, char **err)
{
rule->action = ACT_CUSTOM;
rule->action_ptr = http_req_disable_l7_retry;
return ACT_RET_PRS_OK;
}
/* This function executes the "capture" action. 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
@ -575,6 +607,7 @@ static struct action_kw_list http_req_actions = {
.kw = {
{ "capture", parse_http_req_capture },
{ "reject", parse_http_action_reject },
{ "disable-l7-retry", parse_http_req_disable_l7_retry },
{ "set-method", parse_set_req_line },
{ "set-path", parse_set_req_line },
{ "set-query", parse_set_req_line },

View File

@ -2341,7 +2341,8 @@ redo:
*/
si_b->state = SI_ST_REQ; /* new connection requested */
si_b->conn_retries = s->be->conn_retries;
if (s->be->retry_type &~ PR_RE_CONN_FAILED)
if ((s->be->retry_type &~ PR_RE_CONN_FAILED) &&
!(si_b->flags & SI_FL_D_L7_RETRY))
si_b->flags |= SI_FL_L7_RETRY;
}
}