MINOR: support for http-request set-timeout client
Added set-timeout for frontend side of session, so it can be used to set custom per-client timeouts if needed. Added cur_client_timeout to fetch client timeout samples.
This commit is contained in:
parent
f75a369009
commit
f8b81f6eb7
@ -7010,7 +7010,7 @@ http-request <action> [options...] [ { if | unless } <condition> ]
|
||||
- set-query <fmt>
|
||||
- set-src <expr>
|
||||
- set-src-port <expr>
|
||||
- set-timeout { server | tunnel } { <timeout> | <expr> }
|
||||
- set-timeout { client | server | tunnel } { <timeout> | <expr> }
|
||||
- set-tos <tos>
|
||||
- set-uri <fmt>
|
||||
- set-var(<var-name>[,<cond>...]) <expr>
|
||||
@ -7925,10 +7925,10 @@ http-request set-src-port <expr> [ { if | unless } <condition> ]
|
||||
the address family supports a port, otherwise it forces the source address to
|
||||
IPv4 "0.0.0.0" before rewriting the port.
|
||||
|
||||
http-request set-timeout { server | tunnel } { <timeout> | <expr> }
|
||||
http-request set-timeout { client | server | tunnel } { <timeout> | <expr> }
|
||||
[ { if | unless } <condition> ]
|
||||
|
||||
This action overrides the specified "server" or "tunnel" timeout for the
|
||||
This action overrides the specified "client", "server" or "tunnel" timeout for the
|
||||
current stream only. The timeout can be specified in millisecond or with any
|
||||
other unit if the number is suffixed by the unit as explained at the top of
|
||||
this document. It is also possible to write an expression which must returns
|
||||
@ -7936,8 +7936,8 @@ http-request set-timeout { server | tunnel } { <timeout> | <expr> }
|
||||
|
||||
Note that the server/tunnel timeouts are only relevant on the backend side
|
||||
and thus this rule is only available for the proxies with backend
|
||||
capabilities. Also the timeout value must be non-null to obtain the expected
|
||||
results.
|
||||
capabilities. As well as client timeout is only relevant for frontend side.
|
||||
Also the timeout value must be non-null to obtain the expected results.
|
||||
|
||||
Example:
|
||||
http-request set-timeout tunnel 5s
|
||||
@ -20098,6 +20098,11 @@ cur_tunnel_timeout : integer
|
||||
In the default case, this will be equal to be_tunnel_timeout unless a
|
||||
"set-timeout" rule has been applied. See also "be_tunnel_timeout".
|
||||
|
||||
cur_client_timeout : integer
|
||||
Returns the currently applied client timeout in millisecond for the stream.
|
||||
In the default case, this will be equal to fe_client_timeout unless a
|
||||
"set-timeout" rule has been applied. See also "fe_client_timeout".
|
||||
|
||||
dst : ip
|
||||
This is the destination IP address of the connection on the client side,
|
||||
which is the address the client connected to. Any tcp/http rules may alter
|
||||
@ -20353,7 +20358,7 @@ fe_name : string
|
||||
|
||||
fe_client_timeout : integer
|
||||
Returns the configuration value in millisecond for the client timeout of the
|
||||
current frontend.
|
||||
current frontend. This timeout can be overwritten by a "set-timeout" rule.
|
||||
|
||||
res.timer.data : integer
|
||||
this is the total transfer time of the response payload till the last byte
|
||||
|
@ -99,6 +99,7 @@ enum act_name {
|
||||
enum act_timeout_name {
|
||||
ACT_TIMEOUT_SERVER,
|
||||
ACT_TIMEOUT_TUNNEL,
|
||||
ACT_TIMEOUT_CLIENT,
|
||||
};
|
||||
|
||||
enum act_normalize_uri {
|
||||
|
@ -102,10 +102,8 @@ int check_trk_action(struct act_rule *rule, struct proxy *px, char **err);
|
||||
*/
|
||||
int check_capture(struct act_rule *rule, struct proxy *px, char **err);
|
||||
|
||||
int cfg_parse_rule_set_timeout(const char **args, int idx, int *out_timeout,
|
||||
enum act_timeout_name *name,
|
||||
struct sample_expr **expr, char **err,
|
||||
const char *file, int line, struct arg_list *al);
|
||||
int cfg_parse_rule_set_timeout(const char **args, int idx, struct act_rule *rule,
|
||||
struct proxy *px, char **err);
|
||||
|
||||
static inline void release_timeout_action(struct act_rule *rule)
|
||||
{
|
||||
|
@ -4,7 +4,7 @@ feature ignore_unknown_macro
|
||||
|
||||
#REQUIRE_VERSION=2.4
|
||||
|
||||
server srv_h1 -repeat 3 {
|
||||
server srv_h1 -repeat 5 {
|
||||
rxreq
|
||||
txresp
|
||||
} -start
|
||||
@ -24,6 +24,16 @@ syslog Slog3 -level info {
|
||||
expect ~ "^.*timeout: 5000 3000.*$"
|
||||
} -start
|
||||
|
||||
syslog Slog4 -level info {
|
||||
recv
|
||||
expect ~ "^.*timeout: 5000 5000.*$"
|
||||
} -start
|
||||
|
||||
syslog Slog5 -level info {
|
||||
recv
|
||||
expect ~ "^.*timeout: 5000 3000.*$"
|
||||
} -start
|
||||
|
||||
haproxy hap -conf {
|
||||
defaults
|
||||
timeout connect 5s
|
||||
@ -46,6 +56,14 @@ haproxy hap -conf {
|
||||
http-request set-timeout server 5s
|
||||
server srv_h1 ${srv_h1_addr}:${srv_h1_port}
|
||||
|
||||
listen li3
|
||||
mode http
|
||||
bind "fd@${li3}"
|
||||
log-format "timeout: %[fe_client_timeout] %[cur_client_timeout]"
|
||||
log ${Slog4_addr}:${Slog4_port} len 2048 local0 debug err
|
||||
http-request set-timeout client 5s
|
||||
server srv_h1 ${srv_h1_addr}:${srv_h1_port}
|
||||
|
||||
frontend fe1
|
||||
mode http
|
||||
bind "fd@${fe1}"
|
||||
@ -57,6 +75,18 @@ haproxy hap -conf {
|
||||
mode http
|
||||
http-request set-timeout server int(3),mul(1000)
|
||||
server srv_h1 ${srv_h1_addr}:${srv_h1_port}
|
||||
|
||||
frontend fe2
|
||||
mode http
|
||||
bind "fd@${fe2}"
|
||||
log-format "timeout: %[fe_client_timeout] %[cur_client_timeout]"
|
||||
log ${Slog5_addr}:${Slog5_port} len 2048 local0 debug err
|
||||
http-request set-timeout client int(3),mul(1000)
|
||||
default_backend be2
|
||||
|
||||
backend be2
|
||||
mode http
|
||||
server srv_h1 ${srv_h1_addr}:${srv_h1_port}
|
||||
} -start
|
||||
|
||||
client c1 -connect ${hap_li1_sock} {
|
||||
@ -77,6 +107,20 @@ client c3 -connect ${hap_fe1_sock} {
|
||||
expect resp.status == 200
|
||||
} -run
|
||||
|
||||
client c4 -connect ${hap_li3_sock} {
|
||||
txreq
|
||||
rxresp
|
||||
expect resp.status == 200
|
||||
} -run
|
||||
|
||||
client c5 -connect ${hap_fe2_sock} {
|
||||
txreq
|
||||
rxresp
|
||||
expect resp.status == 200
|
||||
} -run
|
||||
|
||||
syslog Slog1 -wait
|
||||
syslog Slog2 -wait
|
||||
syslog Slog3 -wait
|
||||
syslog Slog4 -wait
|
||||
syslog Slog5 -wait
|
||||
|
43
src/action.c
43
src/action.c
@ -174,35 +174,49 @@ int act_resolution_error_cb(struct resolv_requester *requester, int error_code)
|
||||
}
|
||||
|
||||
/* Parse a set-timeout rule statement. It first checks if the timeout name is
|
||||
* valid and returns it in <name>. Then the timeout is parsed as a plain value
|
||||
* and * returned in <out_timeout>. If there is a parsing error, the value is
|
||||
* reparsed as an expression and returned in <expr>.
|
||||
* valid and proxy is capable of handling it, and returns it in <rule->arg.timeout.type>.
|
||||
* Then the timeout is parsed as a plain value and * returned in <rule->arg.timeout.value>.
|
||||
* If there is a parsing error, the value is reparsed as an expression and
|
||||
* returned in <rule->arg.timeout.expr>.
|
||||
*
|
||||
* Returns -1 if the name is invalid or neither a time or an expression can be
|
||||
* parsed, or if the timeout value is 0.
|
||||
*/
|
||||
int cfg_parse_rule_set_timeout(const char **args, int idx, int *out_timeout,
|
||||
enum act_timeout_name *name,
|
||||
struct sample_expr **expr, char **err,
|
||||
const char *file, int line, struct arg_list *al)
|
||||
int cfg_parse_rule_set_timeout(const char **args, int idx, struct act_rule *rule,
|
||||
struct proxy *px, char **err)
|
||||
{
|
||||
const char *res;
|
||||
const char *timeout_name = args[idx++];
|
||||
|
||||
if (strcmp(timeout_name, "server") == 0) {
|
||||
*name = ACT_TIMEOUT_SERVER;
|
||||
if (!(px->cap & PR_CAP_BE)) {
|
||||
memprintf(err, "'%s' has no backend capability", px->id);
|
||||
return -1;
|
||||
}
|
||||
rule->arg.timeout.type = ACT_TIMEOUT_SERVER;
|
||||
}
|
||||
else if (strcmp(timeout_name, "tunnel") == 0) {
|
||||
*name = ACT_TIMEOUT_TUNNEL;
|
||||
if (!(px->cap & PR_CAP_BE)) {
|
||||
memprintf(err, "'%s' has no backend capability", px->id);
|
||||
return -1;
|
||||
}
|
||||
rule->arg.timeout.type = ACT_TIMEOUT_TUNNEL;
|
||||
}
|
||||
else if (strcmp(timeout_name, "client") == 0) {
|
||||
if (!(px->cap & PR_CAP_FE)) {
|
||||
memprintf(err, "'%s' has no frontend capability", px->id);
|
||||
return -1;
|
||||
}
|
||||
rule->arg.timeout.type = ACT_TIMEOUT_CLIENT;
|
||||
}
|
||||
else {
|
||||
memprintf(err,
|
||||
"'set-timeout' rule supports 'server'/'tunnel' (got '%s')",
|
||||
"'set-timeout' rule supports 'server'/'tunnel'/'client' (got '%s')",
|
||||
timeout_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = parse_time_err(args[idx], (unsigned int *)out_timeout, TIME_UNIT_MS);
|
||||
res = parse_time_err(args[idx], (unsigned int *)&rule->arg.timeout.value, TIME_UNIT_MS);
|
||||
if (res == PARSE_TIME_OVER) {
|
||||
memprintf(err, "timer overflow in argument '%s' to rule 'set-timeout %s' (maximum value is 2147483647 ms or ~24.8 days)",
|
||||
args[idx], timeout_name);
|
||||
@ -215,14 +229,15 @@ int cfg_parse_rule_set_timeout(const char **args, int idx, int *out_timeout,
|
||||
}
|
||||
/* res not NULL, parsing error */
|
||||
else if (res) {
|
||||
*expr = sample_parse_expr((char **)args, &idx, file, line, err, al, NULL);
|
||||
if (!*expr) {
|
||||
rule->arg.timeout.expr = sample_parse_expr((char **)args, &idx, px->conf.args.file,
|
||||
px->conf.args.line, err, &px->conf.args, NULL);
|
||||
if (!rule->arg.timeout.expr) {
|
||||
memprintf(err, "unexpected character '%c' in rule 'set-timeout %s'", *res, timeout_name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* res NULL, parsing ok but value is 0 */
|
||||
else if (!(*out_timeout)) {
|
||||
else if (!(rule->arg.timeout.value)) {
|
||||
memprintf(err, "null value is not valid for a 'set-timeout %s' rule",
|
||||
timeout_name);
|
||||
return -1;
|
||||
|
@ -2192,18 +2192,7 @@ static enum act_parse_ret parse_http_set_timeout(const char **args,
|
||||
return ACT_RET_PRS_ERR;
|
||||
}
|
||||
|
||||
if (!(px->cap & PR_CAP_BE)) {
|
||||
memprintf(err, "proxy '%s' has no backend capability", px->id);
|
||||
return ACT_RET_PRS_ERR;
|
||||
}
|
||||
|
||||
if (cfg_parse_rule_set_timeout(args, cur_arg,
|
||||
&rule->arg.timeout.value,
|
||||
&rule->arg.timeout.type,
|
||||
&rule->arg.timeout.expr,
|
||||
err,
|
||||
px->conf.args.file,
|
||||
px->conf.args.line, &px->conf.args) == -1) {
|
||||
if (cfg_parse_rule_set_timeout(args, cur_arg, rule, px, err) == -1) {
|
||||
return ACT_RET_PRS_ERR;
|
||||
}
|
||||
|
||||
|
16
src/stream.c
16
src/stream.c
@ -867,6 +867,10 @@ void stream_retnclose(struct stream *s, const struct buffer *msg)
|
||||
int stream_set_timeout(struct stream *s, enum act_timeout_name name, int timeout)
|
||||
{
|
||||
switch (name) {
|
||||
case ACT_TIMEOUT_CLIENT:
|
||||
s->scf->ioto = timeout;
|
||||
return 1;
|
||||
|
||||
case ACT_TIMEOUT_SERVER:
|
||||
s->scb->ioto = timeout;
|
||||
return 1;
|
||||
@ -3939,6 +3943,17 @@ static struct action_kw_list stream_http_after_res_actions = { ILH, {
|
||||
|
||||
INITCALL1(STG_REGISTER, http_after_res_keywords_register, &stream_http_after_res_actions);
|
||||
|
||||
static int smp_fetch_cur_client_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
|
||||
{
|
||||
smp->flags = SMP_F_VOL_TXN;
|
||||
smp->data.type = SMP_T_SINT;
|
||||
if (!smp->strm)
|
||||
return 0;
|
||||
|
||||
smp->data.u.sint = TICKS_TO_MS(smp->strm->scf->ioto);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int smp_fetch_cur_server_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
|
||||
{
|
||||
smp->flags = SMP_F_VOL_TXN;
|
||||
@ -3989,6 +4004,7 @@ static int smp_fetch_last_rule_line(const struct arg *args, struct sample *smp,
|
||||
* Please take care of keeping this list alphabetically sorted.
|
||||
*/
|
||||
static struct sample_fetch_kw_list smp_kws = {ILH, {
|
||||
{ "cur_client_timeout", smp_fetch_cur_client_timeout, 0, NULL, SMP_T_SINT, SMP_USE_FTEND, },
|
||||
{ "cur_server_timeout", smp_fetch_cur_server_timeout, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
|
||||
{ "cur_tunnel_timeout", smp_fetch_cur_tunnel_timeout, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
|
||||
{ "last_rule_file", smp_fetch_last_rule_file, 0, NULL, SMP_T_STR, SMP_USE_INTRN, },
|
||||
|
Loading…
x
Reference in New Issue
Block a user