BUG/MEDIUM: http-client: Test HTX_FL_EOM flag before commiting the HTX buffer
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 8 Jul 2025 06:24:45 +0000 (08:24 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Tue, 26 Aug 2025 06:51:46 +0000 (08:51 +0200)
when htx_to_buf() function is called, if the HTX message is empty, the
buffer is reset. So HTX flags must not be tested after because the info may
be lost.

So now, we take care to test HTX_FL_EOM flag before calling htx_to_buf().

This patch must be backported as far as 2.8.

(cherry picked from commit 4bdb2e5a26587120101234c8f73cbc40d1777656)
[wla: API does not emit HTX in response for 3.2, some adjutements were
made to better match the 3.3 behavior]
Signed-off-by: William Lallemand <wlallemand@haproxy.com>
(cherry picked from commit d01fa873acdd5ac40819d311923a28159e01040b)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

src/http_client.c

index b283c5d..327b2c3 100644 (file)
@@ -884,8 +884,6 @@ void httpclient_applet_io_handler(struct appctx *appctx)
                                if (hc->ops.res_stline)
                                        hc->ops.res_stline(hc);
 
-                               htx_to_buf(htx, &res->buf);
-
                                /* if there is no HTX data anymore and the EOM flag is
                                 * set, leave (no body) */
                                if (htx_is_empty(htx) && htx->flags & HTX_FL_EOM)
@@ -893,6 +891,7 @@ void httpclient_applet_io_handler(struct appctx *appctx)
                                else
                                        appctx->st0 = HTTPCLIENT_S_RES_HDR;
 
+                               htx_to_buf(htx, &res->buf);
                                break;
 
                        case HTTPCLIENT_S_RES_HDR:
@@ -932,7 +931,6 @@ void httpclient_applet_io_handler(struct appctx *appctx)
                                                }
                                                blk = htx_remove_blk(htx, blk);
                                        }
-                                       htx_to_buf(htx, &res->buf);
 
                                        if (hdr_num) {
                                                /* alloc and copy the headers in the httpclient struct */
@@ -954,6 +952,7 @@ void httpclient_applet_io_handler(struct appctx *appctx)
                                                appctx->st0 = HTTPCLIENT_S_RES_BODY;
                                        }
                                }
+                               htx_to_buf(htx, &res->buf);
                                break;
 
                        case HTTPCLIENT_S_RES_BODY:
@@ -1025,15 +1024,12 @@ void httpclient_applet_io_handler(struct appctx *appctx)
                                        }
                                }
 
-                               htx_to_buf(htx, &res->buf);
-
                                /* if not finished, should be called again */
-                               if (!(htx_is_empty(htx) && (htx->flags & HTX_FL_EOM)))
-                                       goto out;
+                               if ((htx_is_empty(htx) && (htx->flags & HTX_FL_EOM)))
+                                       appctx->st0 = HTTPCLIENT_S_RES_END;
 
+                               htx_to_buf(htx, &res->buf);
 
-                               /* end of message, we should quit */
-                               appctx->st0 = HTTPCLIENT_S_RES_END;
                                break;
 
                        case HTTPCLIENT_S_RES_END: