From f1571118f064b5f11d62661690dfaf90770e0560 Mon Sep 17 00:00:00 2001 From: crispyberry Date: Sat, 28 Feb 2026 09:48:15 +0800 Subject: [PATCH] hotfix: decode chunked transfer encoding in proxy LLM path The proxy path (llm_http_via_proxy) stripped HTTP headers but did not decode chunked transfer-encoding, leaving hex size prefixes in the body and causing cJSON_Parse to fail with 0 bytes text. Co-Authored-By: Claude Opus 4.6 --- main/llm/llm_proxy.c | 51 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/main/llm/llm_proxy.c b/main/llm/llm_proxy.c index b47f558..c6fa1b8 100644 --- a/main/llm/llm_proxy.c +++ b/main/llm/llm_proxy.c @@ -121,6 +121,54 @@ static void resp_buf_free(resp_buf_t *rb) rb->cap = 0; } +/* ── Chunked transfer encoding decoder ───────────────────────── */ + +static void resp_buf_decode_chunked(resp_buf_t *rb) +{ + if (!rb->data || rb->len == 0) return; + + /* Quick check: if body starts with '{' or '[', it's not chunked */ + size_t i = 0; + while (i < rb->len && (rb->data[i] == ' ' || rb->data[i] == '\t')) i++; + if (i < rb->len && (rb->data[i] == '{' || rb->data[i] == '[')) return; + + /* Try to decode chunked encoding in-place */ + char *src = rb->data; + char *dst = rb->data; + char *end = rb->data + rb->len; + + while (src < end) { + /* Parse hex chunk size */ + char *line_end = strstr(src, "\r\n"); + if (!line_end) break; + + unsigned long chunk_size = strtoul(src, NULL, 16); + if (chunk_size == 0) break; /* terminal chunk */ + + src = line_end + 2; /* skip past \r\n after size */ + + if (src + chunk_size > end) { + /* Incomplete chunk, copy what we have */ + size_t avail = end - src; + memmove(dst, src, avail); + dst += avail; + break; + } + + memmove(dst, src, chunk_size); + dst += chunk_size; + src += chunk_size; + + /* Skip trailing \r\n after chunk data */ + if (src + 2 <= end && src[0] == '\r' && src[1] == '\n') { + src += 2; + } + } + + rb->len = dst - rb->data; + rb->data[rb->len] = '\0'; +} + /* ── HTTP event handler (for esp_http_client direct path) ─────── */ static esp_err_t http_event_handler(esp_http_client_event_t *evt) @@ -298,6 +346,9 @@ static esp_err_t llm_http_via_proxy(const char *post_data, resp_buf_t *rb, int * rb->data[rb->len] = '\0'; } + /* Decode chunked transfer encoding if present */ + resp_buf_decode_chunked(rb); + return ESP_OK; }