From b6d4fa2c2eb77dc6613ea8635c384670b38a2a75 Mon Sep 17 00:00:00 2001 From: "hrushikesh.bhosale" Date: Thu, 17 Apr 2025 11:50:21 +0530 Subject: [PATCH] fix(async_handler): Async handler example scratch buffer fix 1. In httpd_req_async_handler_begin, the httpd_req_aux is locally malloced and data is done memcpy to local httpd_req_aux from request'ss httpd_req_aux for async request use-case, this causes scartch pointer from these two structs pointing to same memory address. 2. In current workflow, the request's sratch buffer is freed in httpd_parse.c httpd_req_cleanup api. Therefore if the user try to fetch the data (like headers) from the scratch buffer, data will be not available. 3. Each request should have the deep copy of the scratch buffer. To retrive the data later. Closes https://github.com/espressif/esp-idf/issues/15587 --- components/esp_http_server/src/httpd_txrx.c | 12 ++++++ .../http_server/async_handlers/main/main.c | 37 ++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/components/esp_http_server/src/httpd_txrx.c b/components/esp_http_server/src/httpd_txrx.c index 0467f7b5a1..0393197cc4 100644 --- a/components/esp_http_server/src/httpd_txrx.c +++ b/components/esp_http_server/src/httpd_txrx.c @@ -647,6 +647,18 @@ esp_err_t httpd_req_async_handler_begin(httpd_req_t *r, httpd_req_t **out) struct httpd_req_aux *async_aux = (struct httpd_req_aux *) async->aux; struct httpd_req_aux *r_aux = (struct httpd_req_aux *) r->aux; + if (r_aux->scratch) { + async_aux->scratch = malloc(r_aux->scratch_cur_size); + if (async_aux->scratch == NULL) { + free(async_aux); + free(async); + return ESP_ERR_NO_MEM; + } + memcpy(async_aux->scratch, r_aux->scratch, r_aux->scratch_cur_size); + } else { + async_aux->scratch = NULL; + } + async_aux->resp_hdrs = calloc(hd->config.max_resp_headers, sizeof(struct resp_hdr)); if (async_aux->resp_hdrs == NULL) { free(async_aux); diff --git a/examples/protocols/http_server/async_handlers/main/main.c b/examples/protocols/http_server/async_handlers/main/main.c index c462ddbfbf..3b383acb88 100644 --- a/examples/protocols/http_server/async_handlers/main/main.c +++ b/examples/protocols/http_server/async_handlers/main/main.c @@ -95,7 +95,42 @@ static esp_err_t queue_request(httpd_req_t *req, httpd_req_handler_t handler) /* handle long request (on async thread) */ static esp_err_t long_async(httpd_req_t *req) { - ESP_LOGI(TAG, "running: /long"); + char* buf; + size_t buf_len; + + /* Get URI */ + ESP_LOGI(TAG, "Request URI: %s", req->uri); + + /* Get header value string length and allocate memory for length + 1, + * extra byte for null termination */ + buf_len = httpd_req_get_hdr_value_len(req, "Host") + 1; + if (buf_len > 1) { + buf = malloc(buf_len); + if (buf == NULL) { + ESP_LOGE(TAG, "Failed to allocate memory for headers"); + return ESP_FAIL; + } + /* Copy null terminated value string into buffer */ + if (httpd_req_get_hdr_value_str(req, "Host", buf, buf_len) == ESP_OK) { + ESP_LOGI(TAG, "Found header => Host: %s", buf); + } + free(buf); + } + /* Get query string length and allocate memory for length + 1, + * extra byte for null termination */ + buf_len = httpd_req_get_url_query_len(req) + 1; + if (buf_len > 1) { + buf = malloc(buf_len); + if (buf == NULL) { + ESP_LOGE(TAG, "Failed to allocate memory for query string"); + return ESP_FAIL; + } + /* Copy null terminated query string into buffer */ + if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) { + ESP_LOGI(TAG, "Found query string => %s", buf); + } + free(buf); + } // track the number of long requests static uint8_t req_count = 0;