mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-20 13:21:29 +02:00
BUG/MEDIUM: http_ana: handle yield for "stats http-request" evaluation
stats http-request rules evaluation is handled separately in http_process_req_common(). Because of that, if a rule requires yielding, the evaluation is interrupted as (F)YIELD verdict return values are not handled there. Since 3.2 with the introduction of costly ruleset interruption in 0846638 ("MEDIUM: stream: interrupt costly rulesets after too many evaluations"), the issue started being more visible because stats http-request rules would be interrupted when the evaluation counters reached tune.max-rules-at-once, but the evaluation would never be resumed, and the request would continue to be handled as if the evaluation was complete. Note however that the issue already existed in the past for actions that could return ACT_RET_YIELD such as "pause" for instance. This issue was reported by GH user @Wahnes in #3087, thanks to him for providing useful repro and details. To fix the issue, we merge rule vedict handling in http_process_req_common() so that "stats http-request" evaluation benefits from all return values already supported for the current ruleset. It should be backported in 3.2 with 0846638 ("MEDIUM: stream: interrupt costly rulesets after too many evaluations"), and probably even further (all stable versions) if the patch adaptation is not to complex (before HTTP_RULE_RES_FYIELD was introduced) because it is still relevant.
This commit is contained in:
parent
f9b227ebff
commit
3da1d63749
@ -383,6 +383,7 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s
|
||||
struct redirect_rule *rule;
|
||||
enum rule_result verdict;
|
||||
struct connection *conn = objt_conn(sess->origin);
|
||||
int stats_rules = 0;
|
||||
|
||||
DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn, msg);
|
||||
|
||||
@ -396,11 +397,21 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s
|
||||
def_rules = ((px->defpx && (an_bit == AN_REQ_HTTP_PROCESS_FE || px != sess->fe)) ? &px->defpx->http_req_rules : NULL);
|
||||
rules = &px->http_req_rules;
|
||||
|
||||
verdict = HTTP_RULE_RES_CONT;
|
||||
|
||||
if (s->current_rule_list == &px->uri_auth->http_req_rules)
|
||||
stats_rules = 1;
|
||||
|
||||
/* resume stats http-request rules if needed */
|
||||
if (stats_rules)
|
||||
verdict = http_req_get_intercept_rule(px, NULL, &px->uri_auth->http_req_rules, s);
|
||||
/* evaluate http-request rules */
|
||||
if ((def_rules && !LIST_ISEMPTY(def_rules)) || !LIST_ISEMPTY(rules)) {
|
||||
else if ((def_rules && !LIST_ISEMPTY(def_rules)) || !LIST_ISEMPTY(rules))
|
||||
verdict = http_req_get_intercept_rule(px, def_rules, rules, s);
|
||||
|
||||
switch (verdict) {
|
||||
rule_verdict:
|
||||
|
||||
switch (verdict) {
|
||||
case HTTP_RULE_RES_YIELD: /* some data miss, call the function later. */
|
||||
goto return_prx_yield;
|
||||
|
||||
@ -428,9 +439,11 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s
|
||||
|
||||
case HTTP_RULE_RES_ERROR: /* failed with a bad request */
|
||||
goto return_int_err;
|
||||
}
|
||||
}
|
||||
|
||||
if (stats_rules)
|
||||
goto resume_stats_rules;
|
||||
|
||||
if (px->options2 & (PR_O2_RSTRICT_REQ_HDR_NAMES_BLK|PR_O2_RSTRICT_REQ_HDR_NAMES_DEL)) {
|
||||
verdict = http_req_restrict_header_names(s, htx, px);
|
||||
if (verdict == HTTP_RULE_RES_DENY)
|
||||
@ -466,23 +479,12 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s
|
||||
/* parse the whole stats request and extract the relevant information */
|
||||
http_handle_stats(s, req, px);
|
||||
verdict = http_req_get_intercept_rule(px, NULL, &px->uri_auth->http_req_rules, s);
|
||||
/* not all actions implemented: deny, allow, auth */
|
||||
|
||||
if (verdict == HTTP_RULE_RES_DENY) /* stats http-request deny */
|
||||
goto deny;
|
||||
|
||||
if (verdict == HTTP_RULE_RES_ABRT) { /* stats auth / stats http-request auth */
|
||||
stream_report_term_evt(s->scf, strm_tevt_type_intercepted);
|
||||
goto return_prx_cond;
|
||||
}
|
||||
|
||||
if (verdict == HTTP_RULE_RES_BADREQ) /* failed with a bad request */
|
||||
goto return_bad_req;
|
||||
|
||||
if (verdict == HTTP_RULE_RES_ERROR) /* failed with a bad request */
|
||||
goto return_int_err;
|
||||
stats_rules = 1;
|
||||
goto rule_verdict;
|
||||
}
|
||||
|
||||
resume_stats_rules:
|
||||
|
||||
/* Proceed with the applets now. */
|
||||
if (unlikely(objt_applet(s->target))) {
|
||||
if (sess->fe == s->be) /* report it if the request was intercepted by the frontend */
|
||||
|
Loading…
x
Reference in New Issue
Block a user