expect-netscaler-cip - X - - - - - -
expect-proxy layer4 - X - - - - - -
normalize-uri - - - - - X - -
+pause - - - - - X X -
redirect - - - - - X X -
reject X X X X X X - -
replace-header - - - - - X X X
- /?aaa=3&a=1&aa=2 -> /?a=1&aa=2&aaa=3
- /?a=3&b=4&a=1&b=5&a=2 -> /?a=3&a=1&a=2&b=4&b=5
+pause { <timeout> | <expr> }
+ Usable in: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft
+ - | - | - | - | - | X | X | -
+
+ This suspends the message analysis for the sepcified number of milliseconds.
+ 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. If the expression evaluation fails
+ or if it returns an invalid value, the action is ignored and the evaluation
+ continues.
+
+ This action may be used for debugging purpose. But it could also be used to
+ slow down some clients based on specific criteria. For instance, it is
+ possible to slow down clients if their requests rate is too high, by tracking
+ them via a "track-sc" rule.
redirect <rule>
Usable in: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft
return ACT_RET_PRS_OK;
}
+/* This function executes a pause action.
+ */
+static enum act_return http_action_pause(struct act_rule *rule, struct proxy *px,
+ struct session *sess, struct stream *s, int flags)
+{
+
+ struct channel *chn = ((rule->from == ACT_F_HTTP_REQ) ? &s->req : &s->res);
+ struct sample *key;
+
+ if (!tick_isset(chn->analyse_exp)) {
+ int time;
+
+ 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;
+ time = MS_TO_TICKS(key->data.u.sint);
+ }
+ else
+ time = MS_TO_TICKS(rule->arg.timeout.value);
+ chn->analyse_exp = tick_add_ifset(now_ms, time);
+ }
+
+ if (tick_isset(chn->analyse_exp) && !tick_is_expired(chn->analyse_exp, now_ms))
+ return ACT_RET_YIELD;
+
+ chn->analyse_exp = TICK_ETERNITY;
+ return ACT_RET_CONT;
+}
+
+/* Parse a "pause" action. It returns ACT_RET_PRS_OK on success,
+ * ACT_RET_PRS_ERR on error.
+ */
+static enum act_parse_ret parse_http_pause(const char **args, int *orig_arg, struct proxy *px,
+ struct act_rule *rule, char **err)
+{
+ const char *res;
+ int cur_arg;
+
+ rule->action = ACT_CUSTOM;
+ rule->action_ptr = http_action_pause;
+ rule->release_ptr = release_timeout_action;
+
+ cur_arg = *orig_arg;
+
+ res = parse_time_err(args[cur_arg], (unsigned int *)&rule->arg.timeout.value, TIME_UNIT_MS);
+ if (res == PARSE_TIME_OVER) {
+ memprintf(err, "timer overflow in argument '%s' to rule 'pause' (maximum value is 2147483647 ms or ~24.8 days)",
+ args[cur_arg]);
+ return ACT_RET_PRS_ERR;
+ }
+ else if (res == PARSE_TIME_UNDER) {
+ memprintf(err, "timer underflow in argument '%s' to rule 'pause' (minimum value is 1 ms)",
+ args[cur_arg]);
+ return ACT_RET_PRS_ERR;
+ }
+ /* res not NULL, parsing error */
+ else if (res) {
+ rule->arg.timeout.expr = sample_parse_expr((char **)args, &cur_arg, 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 'mause'", *res);
+ return ACT_RET_PRS_ERR;
+ }
+ }
+ /* res NULL, parsing ok but value is 0 */
+ else if (!(rule->arg.timeout.value)) {
+ memprintf(err, "null value is not valid for a 'pause' rule");
+ return ACT_RET_PRS_ERR;
+ }
+
+ *orig_arg = cur_arg + 1;
+ return ACT_RET_PRS_OK;
+}
+
+
/* Release memory allocated by an http redirect action. */
static void release_http_redir(struct act_rule *rule)
{
{ "do-log", parse_http_req_do_log, 0 },
{ "early-hint", parse_http_set_header, 0 },
{ "normalize-uri", parse_http_normalize_uri, KWF_EXPERIMENTAL },
+ { "pause", parse_http_pause, 0 },
{ "redirect", parse_http_redirect, 0 },
{ "reject", parse_http_action_reject, 0 },
{ "replace-header", parse_http_replace_header, 0 },
{ "del-map", parse_http_set_map, KWF_MATCH_PREFIX },
{ "deny", parse_http_deny, 0 },
{ "do-log", parse_http_res_do_log, 0 },
+ { "pause", parse_http_pause, 0 },
{ "redirect", parse_http_redirect, 0 },
{ "replace-header", parse_http_replace_header, 0 },
{ "replace-value", parse_http_replace_header, 0 },