From: Christopher Faulet Date: Thu, 4 Jul 2019 09:27:15 +0000 (+0200) Subject: BUG/MEDIUM: http/applet: Finish request processing when a service is registered X-Git-Tag: v2.1-dev1~31 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8f1aa77b423b85012c062149f16ceb8f3aacefea;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: http/applet: Finish request processing when a service is registered In the analyzers AN_REQ_HTTP_PROCESS_FE/BE, when a service is registered, it is important to not interrupt remaining processing but just the http-request rules processing. Otherwise, the part that handles the applets installation is skipped. Among the several effects, if the service is registered on a frontend (not a listen), the forwarding of the request is skipped because all analyzers are not set on the request channel. If the service does not depends on it, the response is still produced and forwarded to the client. But the stream is infinitly blocked because the request is not fully consumed. This issue was reported on Github, see #151. So this bug is fixed thanks to the new action return ACT_RET_DONE. Once a service is registered, the action process_use_service() still returns ACT_RET_STOP. But now, only rules processing is stopped. As a side effet, the action http_action_reject() must now return ACT_RET_DONE to really stop all processing. This patch must be backported to 2.0. It depends on the commit introducing the return code ACT_RET_DONE. --- diff --git a/src/hlua.c b/src/hlua.c index af2400400b..a2669be527 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -6794,7 +6794,7 @@ static enum act_return hlua_action(struct act_rule *rule, struct proxy *px, return ACT_RET_ERR; } if (s->hlua->flags & HLUA_STOP) - return ACT_RET_STOP; + return ACT_RET_DONE; return ACT_RET_CONT; /* yield. */ diff --git a/src/http_act.c b/src/http_act.c index 65d9595c01..0653dd59e8 100644 --- a/src/http_act.c +++ b/src/http_act.c @@ -269,7 +269,7 @@ static enum act_parse_ret parse_http_set_status(const char **args, int *orig_arg * alternative to the silent-drop action to defend against DoS attacks, and may * also be used with HTTP/2 to close a connection instead of just a stream. * The txn status is unchanged, indicating no response was sent. The termination - * flags will indicate "PR". It always returns ACT_RET_STOP. + * flags will indicate "PR". It always returns ACT_RET_DONE. */ static enum act_return http_action_reject(struct act_rule *rule, struct proxy *px, struct session *sess, struct stream *s, int flags) @@ -290,7 +290,7 @@ static enum act_return http_action_reject(struct act_rule *rule, struct proxy *p if (!(s->flags & SF_FINST_MASK)) s->flags |= SF_FINST_R; - return ACT_RET_STOP; + return ACT_RET_DONE; } /* parse the "reject" action: diff --git a/src/proto_http.c b/src/proto_http.c index bfdb199159..35f86ef1dd 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -1788,6 +1788,9 @@ resume_execution: case ACT_RET_CONT: break; case ACT_RET_STOP: + rule_ret = HTTP_RULE_RES_STOP; + goto end; + case ACT_RET_DONE: rule_ret = HTTP_RULE_RES_DONE; goto end; case ACT_RET_YIELD: @@ -2198,6 +2201,9 @@ resume_execution: case ACT_RET_STOP: rule_ret = HTTP_RULE_RES_STOP; goto end; + case ACT_RET_DONE: + rule_ret = HTTP_RULE_RES_DONE; + goto end; case ACT_RET_YIELD: s->current_rule = rule; rule_ret = HTTP_RULE_RES_YIELD; @@ -2588,7 +2594,7 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s * by a possible reqrep, while they are processed *after* so that a * reqdeny can still block them. This clearly needs to change in 1.6! */ - if (stats_check_uri(&s->si[1], txn, px)) { + if (!s->target && stats_check_uri(&s->si[1], txn, px)) { s->target = &http_stats_applet.obj_type; if (unlikely(!si_register_handler(&s->si[1], objt_applet(s->target)))) { txn->status = 500; diff --git a/src/proto_htx.c b/src/proto_htx.c index 6cbd33b9b3..d5119c1000 100644 --- a/src/proto_htx.c +++ b/src/proto_htx.c @@ -540,7 +540,7 @@ int htx_process_req_common(struct stream *s, struct channel *req, int an_bit, st * by a possible reqrep, while they are processed *after* so that a * reqdeny can still block them. This clearly needs to change in 1.6! */ - if (htx_stats_check_uri(s, txn, px)) { + if (!s->target && htx_stats_check_uri(s, txn, px)) { s->target = &http_stats_applet.obj_type; if (unlikely(!si_register_handler(&s->si[1], objt_applet(s->target)))) { txn->status = 500; @@ -3086,6 +3086,9 @@ static enum rule_result htx_req_get_intercept_rule(struct proxy *px, struct list case ACT_RET_CONT: break; case ACT_RET_STOP: + rule_ret = HTTP_RULE_RES_STOP; + goto end; + case ACT_RET_DONE: rule_ret = HTTP_RULE_RES_DONE; goto end; case ACT_RET_YIELD: @@ -3478,6 +3481,9 @@ resume_execution: case ACT_RET_STOP: rule_ret = HTTP_RULE_RES_STOP; goto end; + case ACT_RET_DONE: + rule_ret = HTTP_RULE_RES_DONE; + goto end; case ACT_RET_YIELD: s->current_rule = rule; rule_ret = HTTP_RULE_RES_YIELD;