http-response set-status 503 reason "Slow Down".
-set-timeout { client | server | tunnel } { <timeout> | <expr> }
+set-timeout { client | connect | queue | server | tarpit | tunnel } { <timeout> | <expr> }
Usable in: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft
- | - | - | - | - | X | X | -
- This action overrides the specified "client", "server" or "tunnel" timeout
- for the current stream only. The timeout can be specified in milliseconds 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
- return a number interpreted as a timeout in milliseconds.
-
- 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. Likewise, client timeout is only relevant for frontend side.
- Also the timeout value must be non-null to obtain the expected results.
+ This action overrides the specified "client", "connect", "queue", "server",
+ "tarpit" or "tunnel" timeout for the current stream only. Changing one timeout
+ does not influence any other timeouts, even if they are inherited from each
+ other during configuration parsing (see last example). The timeout can be
+ specified in milliseconds 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 return a number interpreted as a timeout in
+ milliseconds.
+
+ Note that the connect, queue, server and tunnel timeouts are only relevant on
+ the backend side and thus this rule is only available for the proxies with
+ backend capabilities. Likewise, client timeout is only relevant for frontend
+ side. Tarpit timeout is available to both sides. The timeout value must be
+ non-null to obtain the expected results.
Example:
http-request set-timeout tunnel 5s
http-response set-timeout tunnel 5s
http-response set-timeout server res.hdr(X-Refresh-Seconds),mul(1000)
+ Example:
+ defaults
+ # This will set both tarpit and queue timeout to 5s as they are not
+ # defined
+ timeout connect 5s
+ timeout client 30s
+ timeout server 30s
+
+ listen foo
+ # This will only change the connect timeout to 10s without affecting
+ # queue or tarpit timeouts
+ http-request set-timeout connect 10s
set-tos <tos> (deprecated)
This is an alias for "set-fc-tos" (which should be used instead).
bc_srv_queue integer
be_id integer
be_name string
+be_connect_timeout integer
+be_queue_timeout integer
be_server_timeout integer
+be_tarpit_timeout integer
be_tunnel_timeout integer
bytes_in integer
bytes_out integer
+cur_connect_timeout integer
cur_client_timeout integer
+cur_queue_timeout integer
cur_server_timeout integer
+cur_tarpit_timeout integer
cur_tunnel_timeout integer
dst ip
dst_conn integer
fc_src_is_local boolean
fc_src_port integer
fc_unacked integer
+fe_tarpit_timeout integer
fe_client_timeout integer
fe_defbe string
fe_id integer
used in a frontend and no backend was used, it returns the current
frontend's id. It can also be used in a tcp-check or an http-check ruleset.
+be_connect_timeout : integer
+ Returns the configuration value in millisecond for the connect timeout of the
+ current backend. This timeout can be overwritten by a "set-timeout" rule. See
+ also the "cur_connect_timeout".
+
be_name : string
Returns a string containing the current backend's name. It can be used in
frontends with responses to check which backend processed the request. If
frontend's name. It can also be used in a tcp-check or an http-check
ruleset.
+be_queue_timeout : integer
+ Returns the configuration value in millisecond for the queue timeout of the
+ current backend. This timeout can be overwritten by a "set-timeout" rule. See
+ also the "cur_queue_timeout".
+
be_server_timeout : integer
Returns the configuration value in millisecond for the server timeout of the
current backend. This timeout can be overwritten by a "set-timeout" rule. See
also the "cur_server_timeout".
+be_tarpit_timeout : integer
+ Returns the configuration value in millisecond for the queue timeout of the
+ current backend. This timeout can be overwritten by a "set-timeout" rule. See
+ also the "cur_tarpit_timeout".
+
be_tunnel_timeout : integer
Returns the configuration value in millisecond for the tunnel timeout of the
current backend. This timeout can be overwritten by a "set-timeout" rule. See
bytes_out : integer
See "res.bytes_in".
+cur_connect_timeout : integer
+ Returns the currently applied connect timeout in millisecond for the stream.
+ In the default case, this will be equal to be_connect_timeout unless a
+ "set-timeout" rule has been applied. See also "be_connect_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".
+cur_queue_timeout : integer
+ Returns the currently applied queue timeout in millisecond for the stream.
+ In the default case, this will be equal to be_queue_timeout unless a
+ "set-timeout" rule has been applied. See also "be_queue_timeout".
+
cur_server_timeout : integer
Returns the currently applied server timeout in millisecond for the stream.
In the default case, this will be equal to be_server_timeout unless a
"set-timeout" rule has been applied. See also "be_server_timeout".
+cur_tarpit_timeout : integer
+ Returns the currently applied tarpit timeout in millisecond for the stream.
+ In the default case, this will be equal to fe_tarpit_timeout/be_tarpit_timeout
+ unless a "set-timeout" rule has been applied. See also "fe_tarpit_timeout"
+ and "be_tarpit_timeout".
+
cur_tunnel_timeout : integer
Returns the currently applied tunnel timeout in millisecond for the stream.
In the default case, this will be equal to be_tunnel_timeout unless a
backends to check from which frontend it was called, or to stick all users
coming via a same frontend to the same server.
+fe_tarpit_timeout : integer
+ Returns the configuration value in millisecond for the tarpit timeout of the
+ current frontend. This timeout can be overwritten by a "set-timeout" rule.
+
req.bytes_in : integer
This returns the number of bytes received from the client. The value
corresponds to what was received by HAProxy, including some headers and some
/* Timeout name valid for a set-timeout rule */
enum act_timeout_name {
+ ACT_TIMEOUT_CONNECT,
ACT_TIMEOUT_SERVER,
+ ACT_TIMEOUT_QUEUE,
+ ACT_TIMEOUT_TARPIT,
ACT_TIMEOUT_TUNNEL,
ACT_TIMEOUT_CLIENT,
};
struct list *current_rule_list; /* this is used to store the current executed rule list. */
void *current_rule; /* this is used to store the current rule to be resumed. */
int rules_exp; /* expiration date for current rules execution */
- int tunnel_timeout;
+ int tunnel_timeout; /* per-stream tunnel timeout, set by set-timeout action */
+ int connect_timeout; /* per-stream connect timeout, set by set-timeout action */
+ int queue_timeout; /* per-stream queue timeout, set by set-timeout action */
+ int tarpit_timeout; /* per-stream tarpit timeout, set by set-timeout action */
struct {
void *ptr; /* Pointer on the entity (def: NULL) */
const char *res;
const char *timeout_name = args[idx++];
- if (strcmp(timeout_name, "server") == 0) {
+ if (strcmp(timeout_name, "connect") == 0) {
+ if (!(px->cap & PR_CAP_BE)) {
+ memprintf(err, "'%s' has no backend capability", px->id);
+ return -1;
+ }
+ rule->arg.timeout.type = ACT_TIMEOUT_CONNECT;
+ }
+ else if (strcmp(timeout_name, "server") == 0) {
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, "queue") == 0) {
+ if (!(px->cap & PR_CAP_BE)) {
+ memprintf(err, "'%s' has no backend capability", px->id);
+ return -1;
+ }
+ rule->arg.timeout.type = ACT_TIMEOUT_QUEUE;
+ }
+ else if (strcmp(timeout_name, "tarpit") == 0) {
+ rule->arg.timeout.type = ACT_TIMEOUT_TARPIT;
+ }
else if (strcmp(timeout_name, "tunnel") == 0) {
if (!(px->cap & PR_CAP_BE)) {
memprintf(err, "'%s' has no backend capability", px->id);
}
else {
memprintf(err,
- "'set-timeout' rule supports 'server'/'tunnel'/'client' (got '%s')",
+ "'set-timeout' rule supports 'client'/'connect'/'queue'/'server'/'tarpit'/'tunnel' (got '%s')",
timeout_name);
return -1;
}
#endif
/* set connect timeout */
- s->conn_exp = tick_add_ifset(now_ms, s->be->timeout.connect);
+ s->conn_exp = tick_add_ifset(now_ms, s->connect_timeout);
if (srv) {
int count;
return 1;
case SRV_STATUS_QUEUED:
- s->conn_exp = tick_add_ifset(now_ms, s->be->timeout.queue);
+ s->conn_exp = tick_add_ifset(now_ms, s->queue_timeout);
s->scb->state = SC_ST_QUE;
/* handle the unlikely event where we added to the server's
return 1;
}
+static int
+smp_fetch_be_connect_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
+{
+ struct proxy *px = NULL;
+
+ if (smp->strm)
+ px = smp->strm->be;
+ else if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
+ px = __objt_check(smp->sess->origin)->proxy;
+ if (!px)
+ return 0;
+
+ smp->flags = SMP_F_VOL_TXN;
+ smp->data.type = SMP_T_SINT;
+ smp->data.u.sint = TICKS_TO_MS(px->timeout.connect);
+ return 1;
+}
+
+static int
+smp_fetch_be_queue_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
+{
+ struct proxy *px = NULL;
+
+ if (smp->strm)
+ px = smp->strm->be;
+ else if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
+ px = __objt_check(smp->sess->origin)->proxy;
+ if (!px)
+ return 0;
+
+ smp->flags = SMP_F_VOL_TXN;
+ smp->data.type = SMP_T_SINT;
+ smp->data.u.sint = TICKS_TO_MS(px->timeout.queue);
+ return 1;
+}
+
static int
smp_fetch_be_server_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
{
return 1;
}
+static int
+smp_fetch_be_tarpit_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
+{
+ struct proxy *px = NULL;
+
+ if (smp->strm)
+ px = smp->strm->be;
+ else if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
+ px = __objt_check(smp->sess->origin)->proxy;
+ if (!px)
+ return 0;
+
+ smp->flags = SMP_F_VOL_TXN;
+ smp->data.type = SMP_T_SINT;
+ smp->data.u.sint = TICKS_TO_MS(px->timeout.tarpit);
+ return 1;
+}
+
static int
smp_fetch_be_tunnel_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
{
{ "be_conn_free", smp_fetch_be_conn_free, ARG1(1,BE), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "be_id", smp_fetch_be_id, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
{ "be_name", smp_fetch_be_name, 0, NULL, SMP_T_STR, SMP_USE_BKEND, },
+ { "be_connect_timeout",smp_fetch_be_connect_timeout,0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
+ { "be_queue_timeout", smp_fetch_be_queue_timeout, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
{ "be_server_timeout", smp_fetch_be_server_timeout, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
{ "be_sess_rate", smp_fetch_be_sess_rate, ARG1(1,BE), NULL, SMP_T_SINT, SMP_USE_INTRN, },
+ { "be_tarpit_timeout", smp_fetch_be_tarpit_timeout, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
{ "be_tunnel_timeout", smp_fetch_be_tunnel_timeout, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
{ "connslots", smp_fetch_connslots, ARG1(1,BE), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "nbsrv", smp_fetch_nbsrv, ARG1(1,BE), NULL, SMP_T_SINT, SMP_USE_INTRN, },
return 1;
}
+static int
+smp_fetch_fe_tarpit_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;
+ smp->data.u.sint = TICKS_TO_MS(smp->sess->fe->timeout.tarpit);
+ return 1;
+}
+
/* Note: must not be declared <const> as its list will be overwritten.
* Please take care of keeping this list alphabetically sorted.
*/
static struct sample_fetch_kw_list smp_kws = {ILH, {
{ "fe_client_timeout", smp_fetch_fe_client_timeout, 0, NULL, SMP_T_SINT, SMP_USE_FTEND, },
+ { "fe_tarpit_timeout", smp_fetch_fe_tarpit_timeout, 0, NULL, SMP_T_SINT, SMP_USE_FTEND, },
{ "fe_conn", smp_fetch_fe_conn, ARG1(1,FE), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "fe_defbe", smp_fetch_fe_defbe, 0, NULL, SMP_T_STR, SMP_USE_FTEND, },
{ "fe_id", smp_fetch_fe_id, 0, NULL, SMP_T_SINT, SMP_USE_FTEND, },
req->analysers &= AN_REQ_FLT_END; /* remove switching rules etc... */
req->analysers |= AN_REQ_HTTP_TARPIT;
- req->analyse_exp = tick_add_ifset(now_ms, s->be->timeout.tarpit);
+ req->analyse_exp = tick_add_ifset(now_ms, s->tarpit_timeout ? s->tarpit_timeout : s->be->timeout.tarpit);
if (!req->analyse_exp)
req->analyse_exp = tick_add(now_ms, 0);
stream_inc_http_err_ctr(s);
s->resolv_ctx.hostname_dn_len = 0;
s->resolv_ctx.parent = NULL;
+ s->connect_timeout = TICK_ETERNITY;
+ s->queue_timeout = TICK_ETERNITY;
+ s->tarpit_timeout = TICK_ETERNITY;
s->tunnel_timeout = TICK_ETERNITY;
LIST_APPEND(&th_ctx->streams, &s->list);
s->scf->ioto = timeout;
return 1;
+ case ACT_TIMEOUT_CONNECT:
+ s->connect_timeout = timeout;
+ return 1;
+
+ case ACT_TIMEOUT_QUEUE:
+ s->queue_timeout = timeout;
+ return 1;
+
case ACT_TIMEOUT_SERVER:
s->scb->ioto = timeout;
return 1;
+ case ACT_TIMEOUT_TARPIT:
+ s->tarpit_timeout = timeout;
+ return 1;
+
case ACT_TIMEOUT_TUNNEL:
s->tunnel_timeout = timeout;
return 1;
/* Se the max connection retries for the stream. may be overwritten later */
s->max_retries = s->be->conn_retries;
+ /* Set the queue and connect timeouts. May be overwritten later */
+ s->connect_timeout = s->be->timeout.connect;
+ s->queue_timeout = s->be->timeout.queue;
+
/* we don't want to run the TCP or HTTP filters again if the backend has not changed */
if (fe == s->be) {
s->req.analysers &= ~AN_REQ_INSPECT_BE;
INITCALL1(STG_REGISTER, http_after_res_keywords_register, &stream_http_after_res_actions);
+static int smp_fetch_cur_connect_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->connect_timeout);
+ return 1;
+}
+
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;
return 1;
}
+static int smp_fetch_cur_queue_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->queue_timeout);
+ return 1;
+}
+
+static int smp_fetch_cur_tarpit_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;
+
+ if (smp->strm->tarpit_timeout)
+ smp->data.u.sint = TICKS_TO_MS(smp->strm->tarpit_timeout);
+ else if (smp->strm->be)
+ smp->data.u.sint = TICKS_TO_MS(smp->strm->be->timeout.tarpit);
+ else
+ smp->data.u.sint = TICKS_TO_MS(smp->sess->fe->timeout.tarpit);
+
+ return 1;
+}
+
static int smp_fetch_cur_tunnel_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
{
smp->flags = SMP_F_VOL_TXN;
* Please take care of keeping this list alphabetically sorted.
*/
static struct sample_fetch_kw_list smp_kws = {ILH, {
+ { "cur_connect_timeout",smp_fetch_cur_connect_timeout,0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
{ "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_queue_timeout", smp_fetch_cur_queue_timeout, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
+ { "cur_tarpit_timeout", smp_fetch_cur_tarpit_timeout, 0, NULL, SMP_T_SINT, SMP_USE_FTEND | SMP_USE_BKEND, },
{ "cur_tunnel_timeout", smp_fetch_cur_tunnel_timeout, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
{ "last_entity", smp_fetch_last_entity, 0, NULL, SMP_T_STR, SMP_USE_INTRN, },
{ "last_rule_file", smp_fetch_last_rule_file, 0, NULL, SMP_T_STR, SMP_USE_INTRN, },