From 4e57516c9a4a9e8b6b3009626dad867bb37e2609 Mon Sep 17 00:00:00 2001 From: Aleksandar Lazic Date: Sun, 15 Mar 2026 14:37:57 +0100 Subject: [PATCH] OPTIM: haterm: use chunk builders for generated response headers hstream_build_http_resp() currently uses snprintf() to build the status code and the generated X-req/X-rsp header values. These strings are short and are fully derived from already parsed request state, so they can be assembled directly in the HAProxy trash buffer using `chunk_strcat()` and `ultoa_o()`. This keeps the generated output unchanged while removing the remaining `snprintf()` calls from the response-building path. No functional change is expected. Signed-off-by: Aleksandar Lazic --- src/haterm.c | 51 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/src/haterm.c b/src/haterm.c index 98100f83e..908a471c4 100644 --- a/src/haterm.c +++ b/src/haterm.c @@ -501,11 +501,14 @@ static int hstream_build_http_resp(struct hstream *hs) struct htx *htx; unsigned int flags = HTX_SL_F_IS_RESP | HTX_SL_F_XFER_LEN | (!hs->req_chunked ? HTX_SL_F_CLEN : 0); struct htx_sl *sl; - char hdrbuf[128]; + char *end; TRACE_ENTER(HS_EV_HSTRM_RESP, hs); - snprintf(hdrbuf, sizeof(hdrbuf), "%d", hs->req_code); + chunk_reset(&trash); + end = ultoa_o(hs->req_code, trash.area, trash.size); + if (!end) + goto err; buf = hstream_get_buf(hs, &hs->res); if (!buf) { TRACE_ERROR("could not allocate response buffer", HS_EV_HSTRM_RESP, hs); @@ -515,7 +518,7 @@ static int hstream_build_http_resp(struct hstream *hs) htx = htx_from_buf(buf); sl = htx_add_stline(htx, HTX_BLK_RES_SL, flags, !(hs->ka & 4) ? ist("HTTP/1.0") : ist("HTTP/1.1"), - ist(hdrbuf), IST_NULL); + ist2(trash.area, end - trash.area), IST_NULL); if (!sl) { TRACE_ERROR("could not add HTX start line", HS_EV_HSTRM_RESP, hs); goto err; @@ -550,18 +553,46 @@ static int hstream_build_http_resp(struct hstream *hs) } /* XXX TODO time? XXX */ - snprintf(hdrbuf, sizeof(hdrbuf), "time=%ld ms", 0L); - if (!htx_add_header(htx, ist("X-req"), ist(hdrbuf))) { + chunk_reset(&trash); + if (!chunk_strcat(&trash, "time=0 ms") || + !htx_add_header(htx, ist("X-req"), ist2(trash.area, trash.data))) { TRACE_ERROR("could not add x-req HTX header", HS_EV_HSTRM_RESP, hs); goto err; } /* XXX TODO time? XXX */ - snprintf(hdrbuf, sizeof(hdrbuf), "id=%s, code=%d, cache=%d,%s size=%lld, time=%d ms (%ld real)", - "dummy", hs->req_code, hs->req_cache, - hs->req_chunked ? " chunked," : "", - hs->req_size, 0, 0L); - if (!htx_add_header(htx, ist("X-rsp"), ist(hdrbuf))) { + chunk_reset(&trash); + if (!chunk_strcat(&trash, "id=dummy, code=")) { + TRACE_ERROR("could not build x-rsp HTX header", HS_EV_HSTRM_RESP, hs); + goto err; + } + end = ultoa_o(hs->req_code, trash.area + trash.data, trash.size - trash.data); + if (!end) + goto err; + trash.data = end - trash.area; + if (!chunk_strcat(&trash, ", cache=")) { + TRACE_ERROR("could not build x-rsp HTX header", HS_EV_HSTRM_RESP, hs); + goto err; + } + end = ultoa_o(hs->req_cache, trash.area + trash.data, trash.size - trash.data); + if (!end) + goto err; + trash.data = end - trash.area; + if (hs->req_chunked && !chunk_strcat(&trash, ", chunked,")) { + TRACE_ERROR("could not build x-rsp HTX header", HS_EV_HSTRM_RESP, hs); + goto err; + } + if (!chunk_strcat(&trash, " size=")) { + TRACE_ERROR("could not build x-rsp HTX header", HS_EV_HSTRM_RESP, hs); + goto err; + } + end = ultoa_o(hs->req_size, trash.area + trash.data, trash.size - trash.data); + if (!end) + goto err; + trash.data = end - trash.area; + + if (!chunk_strcat(&trash, ", time=0 ms (0 real)") || + !htx_add_header(htx, ist("X-rsp"), ist2(trash.area, trash.data))) { TRACE_ERROR("could not add x-rsp HTX header", HS_EV_HSTRM_RESP, hs); goto err; }