]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: http-ana: Don't ignore L7 retry errors
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 12 Jun 2026 13:57:50 +0000 (15:57 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 15 Jun 2026 06:55:56 +0000 (08:55 +0200)
with L7 retries are configured, when the max number of retries is reached
the error must be reported to the client. However, when it was an abort on a
reused connections, the client connection is silently closed. While it is
expected without L7 retries, to let the client retries on its own, it is
unexepcted with L7 retries.

So let's fix it by ignoring the SF_SRV_REUSED flag on the stream when a L7
retry fails. This way, a 502/425 will be reported to the client.

This patch should help to fix the issue #3414. It must be backported to all
supported versions.

src/http_ana.c

index d2d270fa8ffb3f0a078f178023debcadcff6a1b4..4806afd653793f447f1f7dc6bb4d33d4035ca628 100644 (file)
@@ -1265,7 +1265,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
        struct htx *htx;
        struct connection *srv_conn;
        struct htx_sl *sl;
-       int n;
+       int n, l7_retry_failed = 0;
 
        DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn, msg);
 
@@ -1306,19 +1306,22 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
                            (!conn || conn->err_code != CO_ER_SSL_EARLY_FAILED)) {
                                if (co_data(rep) || do_l7_retry(s, s->scb) == 0)
                                        return 0;
+                               l7_retry_failed = 1;
                        }
 
                        /* Perform a L7 retry on empty response or because server refuses the early data. */
                        if ((txn->flags & TX_L7_RETRY) &&
                            (s->be->retry_type & PR_RE_EARLY_ERROR) &&
-                           conn && conn->err_code == CO_ER_SSL_EARLY_FAILED &&
-                           do_l7_retry(s, s->scb) == 0) {
-                               DBG_TRACE_DEVEL("leaving on L7 retry",
-                                               STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
-                               return 0;
+                           conn && conn->err_code == CO_ER_SSL_EARLY_FAILED) {
+                               if (do_l7_retry(s, s->scb) == 0) {
+                                       DBG_TRACE_DEVEL("leaving on L7 retry",
+                                                       STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
+                                       return 0;
+                               }
+                               l7_retry_failed = 1;
                        }
 
-                       if (s->flags & SF_SRV_REUSED)
+                       if (!l7_retry_failed && (s->flags & SF_SRV_REUSED))
                                goto abort_keep_alive;
 
                        if (s->be_tgcounters)
@@ -1416,9 +1419,10 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
                                                        STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
                                        return 0;
                                }
+                               l7_retry_failed = 1;
                        }
 
-                       if (s->flags & SF_SRV_REUSED)
+                       if (!l7_retry_failed && (s->flags & SF_SRV_REUSED))
                                goto abort_keep_alive;
 
                        if (s->be_tgcounters)