mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-20 21:31:28 +02:00
MEDIUM: http_act: define set-timeout server/tunnel action
Add a new http-request action 'set-timeout [server/tunnel]'. This action can be used to update the server or tunnel timeout of a stream. It takes two parameters, the timeout name to update and the new timeout value. This rule is only valid for a proxy with backend capabilities. The timeout value cannot be null. A sample expression can also be used instead of a plain value.
This commit is contained in:
parent
fb50443517
commit
8d22823ade
@ -6265,6 +6265,24 @@ 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> }
|
||||||
|
[ { if | unless } <condition> ]
|
||||||
|
|
||||||
|
This action overrides the specified "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
|
||||||
|
a number interpreted as a timeout in millisecond.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
http-request set-timeout server 5s
|
||||||
|
http-request set-timeout hdr(host),map_int(host.lst)
|
||||||
|
|
||||||
http-request set-tos <tos> [ { if | unless } <condition> ]
|
http-request set-tos <tos> [ { if | unless } <condition> ]
|
||||||
|
|
||||||
This is used to set the TOS or DSCP field value of packets sent to the client
|
This is used to set the TOS or DSCP field value of packets sent to the client
|
||||||
|
@ -143,6 +143,11 @@ struct act_rule {
|
|||||||
struct sample_expr *expr;
|
struct sample_expr *expr;
|
||||||
int idx;
|
int idx;
|
||||||
} capid;
|
} capid;
|
||||||
|
struct {
|
||||||
|
int value; /* plain timeout value in ms if no expr is used */
|
||||||
|
enum act_timeout_name type; /* timeout type */
|
||||||
|
struct sample_expr *expr; /* timeout value as an expression */
|
||||||
|
} timeout;
|
||||||
struct hlua_rule *hlua_rule;
|
struct hlua_rule *hlua_rule;
|
||||||
struct {
|
struct {
|
||||||
struct sample_expr *expr;
|
struct sample_expr *expr;
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <haproxy/action-t.h>
|
#include <haproxy/action-t.h>
|
||||||
#include <haproxy/list.h>
|
#include <haproxy/list.h>
|
||||||
|
#include <haproxy/sample.h>
|
||||||
|
|
||||||
int act_resolution_cb(struct dns_requester *requester, struct dns_nameserver *nameserver);
|
int act_resolution_cb(struct dns_requester *requester, struct dns_nameserver *nameserver);
|
||||||
int act_resolution_error_cb(struct dns_requester *requester, int error_code);
|
int act_resolution_error_cb(struct dns_requester *requester, int error_code);
|
||||||
@ -90,4 +91,14 @@ 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,
|
||||||
|
enum act_timeout_name *name,
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
release_sample_expr(rule->arg.timeout.expr);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _HAPROXY_ACTION_H */
|
#endif /* _HAPROXY_ACTION_H */
|
||||||
|
57
src/action.c
57
src/action.c
@ -149,3 +149,60 @@ int act_resolution_error_cb(struct dns_requester *requester, int error_code)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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>.
|
||||||
|
*
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
const char *res;
|
||||||
|
const char *timeout_name = args[idx++];
|
||||||
|
|
||||||
|
if (!strcmp(timeout_name, "server")) {
|
||||||
|
*name = ACT_TIMEOUT_SERVER;
|
||||||
|
}
|
||||||
|
else if (!strcmp(timeout_name, "tunnel")) {
|
||||||
|
*name = ACT_TIMEOUT_TUNNEL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memprintf(err,
|
||||||
|
"'set-timeout' rule supports 'server'/'tunnel' (got '%s')",
|
||||||
|
timeout_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = parse_time_err(args[idx], (unsigned int *)out_timeout, 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);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (res == PARSE_TIME_UNDER) {
|
||||||
|
memprintf(err, "timer underflow in argument '%s' to rule 'set-timeout %s' (minimum value is 1 ms)",
|
||||||
|
args[idx], timeout_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* res not NULL, parsing error */
|
||||||
|
else if (res) {
|
||||||
|
*expr = sample_parse_expr((char **)args, &idx, file, line, err, al, NULL);
|
||||||
|
if (!*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)) {
|
||||||
|
memprintf(err, "null value is not valid for a 'set-timeout %s' rule",
|
||||||
|
timeout_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -1901,6 +1901,67 @@ static enum act_parse_ret parse_http_track_sc(const char **args, int *orig_arg,
|
|||||||
return ACT_RET_PRS_OK;
|
return ACT_RET_PRS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum act_return action_timeout_set_stream_timeout(struct act_rule *rule,
|
||||||
|
struct proxy *px,
|
||||||
|
struct session *sess,
|
||||||
|
struct stream *s,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
struct sample *key;
|
||||||
|
|
||||||
|
if (rule->arg.timeout.expr) {
|
||||||
|
key = sample_fetch_as_type(px, sess, s, SMP_OPT_FINAL, rule->arg.timeout.expr, SMP_T_SINT);
|
||||||
|
if (!key)
|
||||||
|
return ACT_RET_CONT;
|
||||||
|
|
||||||
|
stream_set_timeout(s, rule->arg.timeout.type, MS_TO_TICKS(key->data.u.sint));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stream_set_timeout(s, rule->arg.timeout.type, MS_TO_TICKS(rule->arg.timeout.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ACT_RET_CONT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse a "set-timeout" action. Returns ACT_RET_PRS_ERR if parsing error.
|
||||||
|
*/
|
||||||
|
static enum act_parse_ret parse_http_set_timeout(const char **args,
|
||||||
|
int *orig_arg,
|
||||||
|
struct proxy *px,
|
||||||
|
struct act_rule *rule, char **err)
|
||||||
|
{
|
||||||
|
int cur_arg;
|
||||||
|
|
||||||
|
rule->action = ACT_CUSTOM;
|
||||||
|
rule->action_ptr = action_timeout_set_stream_timeout;
|
||||||
|
rule->release_ptr = release_timeout_action;
|
||||||
|
|
||||||
|
cur_arg = *orig_arg;
|
||||||
|
if (!*args[cur_arg] || !*args[cur_arg + 1]) {
|
||||||
|
memprintf(err, "expects exactly 2 arguments");
|
||||||
|
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) {
|
||||||
|
return ACT_RET_PRS_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*orig_arg = cur_arg + 2;
|
||||||
|
|
||||||
|
return ACT_RET_PRS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* This function executes a strict-mode actions. On success, it always returns
|
/* This function executes a strict-mode actions. On success, it always returns
|
||||||
* ACT_RET_CONT
|
* ACT_RET_CONT
|
||||||
*/
|
*/
|
||||||
@ -2034,6 +2095,7 @@ static struct action_kw_list http_req_actions = {
|
|||||||
{ "strict-mode", parse_http_strict_mode, 0 },
|
{ "strict-mode", parse_http_strict_mode, 0 },
|
||||||
{ "tarpit", parse_http_deny, 0 },
|
{ "tarpit", parse_http_deny, 0 },
|
||||||
{ "track-sc", parse_http_track_sc, 1 },
|
{ "track-sc", parse_http_track_sc, 1 },
|
||||||
|
{ "set-timeout", parse_http_set_timeout, 0 },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user