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-query <fmt>
|
||||||
- set-src <expr>
|
- set-src <expr>
|
||||||
- set-src-port <expr>
|
- set-src-port <expr>
|
||||||
- set-timeout { server | tunnel } { <timeout> | <expr> }
|
- set-timeout { client | server | tunnel } { <timeout> | <expr> }
|
||||||
- set-tos <tos>
|
- set-tos <tos>
|
||||||
- set-uri <fmt>
|
- set-uri <fmt>
|
||||||
- set-var(<var-name>[,<cond>...]) <expr>
|
- 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
|
the address family supports a port, otherwise it forces the source address to
|
||||||
IPv4 "0.0.0.0" before rewriting the port.
|
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> ]
|
[ { 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
|
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
|
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
|
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
|
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
|
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
|
capabilities. As well as client timeout is only relevant for frontend side.
|
||||||
results.
|
Also the timeout value must be non-null to obtain the expected results.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
http-request set-timeout tunnel 5s
|
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
|
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".
|
"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
|
dst : ip
|
||||||
This is the destination IP address of the connection on the client side,
|
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
|
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
|
fe_client_timeout : integer
|
||||||
Returns the configuration value in millisecond for the client timeout of the
|
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
|
res.timer.data : integer
|
||||||
this is the total transfer time of the response payload till the last byte
|
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 {
|
enum act_timeout_name {
|
||||||
ACT_TIMEOUT_SERVER,
|
ACT_TIMEOUT_SERVER,
|
||||||
ACT_TIMEOUT_TUNNEL,
|
ACT_TIMEOUT_TUNNEL,
|
||||||
|
ACT_TIMEOUT_CLIENT,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum act_normalize_uri {
|
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 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,
|
int cfg_parse_rule_set_timeout(const char **args, int idx, struct act_rule *rule,
|
||||||
enum act_timeout_name *name,
|
struct proxy *px, char **err);
|
||||||
struct sample_expr **expr, char **err,
|
|
||||||
const char *file, int line, struct arg_list *al);
|
|
||||||
|
|
||||||
static inline void release_timeout_action(struct act_rule *rule)
|
static inline void release_timeout_action(struct act_rule *rule)
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,7 @@ feature ignore_unknown_macro
|
|||||||
|
|
||||||
#REQUIRE_VERSION=2.4
|
#REQUIRE_VERSION=2.4
|
||||||
|
|
||||||
server srv_h1 -repeat 3 {
|
server srv_h1 -repeat 5 {
|
||||||
rxreq
|
rxreq
|
||||||
txresp
|
txresp
|
||||||
} -start
|
} -start
|
||||||
@ -24,6 +24,16 @@ syslog Slog3 -level info {
|
|||||||
expect ~ "^.*timeout: 5000 3000.*$"
|
expect ~ "^.*timeout: 5000 3000.*$"
|
||||||
} -start
|
} -start
|
||||||
|
|
||||||
|
syslog Slog4 -level info {
|
||||||
|
recv
|
||||||
|
expect ~ "^.*timeout: 5000 5000.*$"
|
||||||
|
} -start
|
||||||
|
|
||||||
|
syslog Slog5 -level info {
|
||||||
|
recv
|
||||||
|
expect ~ "^.*timeout: 5000 3000.*$"
|
||||||
|
} -start
|
||||||
|
|
||||||
haproxy hap -conf {
|
haproxy hap -conf {
|
||||||
defaults
|
defaults
|
||||||
timeout connect 5s
|
timeout connect 5s
|
||||||
@ -46,6 +56,14 @@ haproxy hap -conf {
|
|||||||
http-request set-timeout server 5s
|
http-request set-timeout server 5s
|
||||||
server srv_h1 ${srv_h1_addr}:${srv_h1_port}
|
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
|
frontend fe1
|
||||||
mode http
|
mode http
|
||||||
bind "fd@${fe1}"
|
bind "fd@${fe1}"
|
||||||
@ -57,6 +75,18 @@ haproxy hap -conf {
|
|||||||
mode http
|
mode http
|
||||||
http-request set-timeout server int(3),mul(1000)
|
http-request set-timeout server int(3),mul(1000)
|
||||||
server srv_h1 ${srv_h1_addr}:${srv_h1_port}
|
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
|
} -start
|
||||||
|
|
||||||
client c1 -connect ${hap_li1_sock} {
|
client c1 -connect ${hap_li1_sock} {
|
||||||
@ -77,6 +107,20 @@ client c3 -connect ${hap_fe1_sock} {
|
|||||||
expect resp.status == 200
|
expect resp.status == 200
|
||||||
} -run
|
} -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 Slog1 -wait
|
||||||
syslog Slog2 -wait
|
syslog Slog2 -wait
|
||||||
syslog Slog3 -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
|
/* 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
|
* valid and proxy is capable of handling it, and returns it in <rule->arg.timeout.type>.
|
||||||
* and * returned in <out_timeout>. If there is a parsing error, the value is
|
* Then the timeout is parsed as a plain value and * returned in <rule->arg.timeout.value>.
|
||||||
* reparsed as an expression and returned in <expr>.
|
* 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
|
* Returns -1 if the name is invalid or neither a time or an expression can be
|
||||||
* parsed, or if the timeout value is 0.
|
* parsed, or if the timeout value is 0.
|
||||||
*/
|
*/
|
||||||
int cfg_parse_rule_set_timeout(const char **args, int idx, int *out_timeout,
|
int cfg_parse_rule_set_timeout(const char **args, int idx, struct act_rule *rule,
|
||||||
enum act_timeout_name *name,
|
struct proxy *px, char **err)
|
||||||
struct sample_expr **expr, char **err,
|
|
||||||
const char *file, int line, struct arg_list *al)
|
|
||||||
{
|
{
|
||||||
const char *res;
|
const char *res;
|
||||||
const char *timeout_name = args[idx++];
|
const char *timeout_name = args[idx++];
|
||||||
|
|
||||||
if (strcmp(timeout_name, "server") == 0) {
|
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) {
|
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 {
|
else {
|
||||||
memprintf(err,
|
memprintf(err,
|
||||||
"'set-timeout' rule supports 'server'/'tunnel' (got '%s')",
|
"'set-timeout' rule supports 'server'/'tunnel'/'client' (got '%s')",
|
||||||
timeout_name);
|
timeout_name);
|
||||||
return -1;
|
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) {
|
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)",
|
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);
|
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 */
|
/* res not NULL, parsing error */
|
||||||
else if (res) {
|
else if (res) {
|
||||||
*expr = sample_parse_expr((char **)args, &idx, file, line, err, al, NULL);
|
rule->arg.timeout.expr = sample_parse_expr((char **)args, &idx, px->conf.args.file,
|
||||||
if (!*expr) {
|
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);
|
memprintf(err, "unexpected character '%c' in rule 'set-timeout %s'", *res, timeout_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* res NULL, parsing ok but value is 0 */
|
/* 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",
|
memprintf(err, "null value is not valid for a 'set-timeout %s' rule",
|
||||||
timeout_name);
|
timeout_name);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2192,18 +2192,7 @@ static enum act_parse_ret parse_http_set_timeout(const char **args,
|
|||||||
return ACT_RET_PRS_ERR;
|
return ACT_RET_PRS_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(px->cap & PR_CAP_BE)) {
|
if (cfg_parse_rule_set_timeout(args, cur_arg, rule, px, err) == -1) {
|
||||||
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) {
|
|
||||||
return ACT_RET_PRS_ERR;
|
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)
|
int stream_set_timeout(struct stream *s, enum act_timeout_name name, int timeout)
|
||||||
{
|
{
|
||||||
switch (name) {
|
switch (name) {
|
||||||
|
case ACT_TIMEOUT_CLIENT:
|
||||||
|
s->scf->ioto = timeout;
|
||||||
|
return 1;
|
||||||
|
|
||||||
case ACT_TIMEOUT_SERVER:
|
case ACT_TIMEOUT_SERVER:
|
||||||
s->scb->ioto = timeout;
|
s->scb->ioto = timeout;
|
||||||
return 1;
|
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);
|
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)
|
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;
|
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.
|
* Please take care of keeping this list alphabetically sorted.
|
||||||
*/
|
*/
|
||||||
static struct sample_fetch_kw_list smp_kws = {ILH, {
|
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_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, },
|
{ "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, },
|
{ "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