From 30758d9beb7b317e49d4a8578c920100591fb973 Mon Sep 17 00:00:00 2001 From: Richard Allen Date: Fri, 16 May 2025 12:54:15 -0500 Subject: [PATCH] feat(esp_http_client): Event to signal last header download When parsing ND-JSON streams, this is needed to indicate the point when the ND-JSON stream is considered open, which occurs just after the last HTTP_EVENT_ON_HEADER. ND-JSON stream clients cannot rely on the first HTTP_EVENT_ON_DATA, since that is only triggered by an event, which are optional and may never be sent, or only sent well after the last HTTP_EVENT_ON_HEADER. Closes #15952 --- .../esp_eth/test_apps/main/esp_eth_test_apps.c | 3 +++ components/esp_http_client/esp_http_client.c | 2 ++ .../esp_http_client/include/esp_http_client.h | 1 + .../api-reference/protocols/esp_http_client.rst | 17 +++++++++-------- .../api-reference/protocols/esp_http_client.rst | 17 +++++++++-------- .../components/dns_over_https/dns_over_https.c | 3 +++ .../main/esp_http_client_example.c | 3 +++ .../system/ota/partitions_ota/main/app_main.c | 3 +++ .../main/simple_ota_example.c | 3 +++ 9 files changed, 36 insertions(+), 16 deletions(-) diff --git a/components/esp_eth/test_apps/main/esp_eth_test_apps.c b/components/esp_eth/test_apps/main/esp_eth_test_apps.c index e4e138bebf..9f855bfe77 100644 --- a/components/esp_eth/test_apps/main/esp_eth_test_apps.c +++ b/components/esp_eth/test_apps/main/esp_eth_test_apps.c @@ -623,6 +623,9 @@ esp_err_t http_event_handle(esp_http_client_event_t *evt) case HTTP_EVENT_ON_HEADER: ESP_LOGI(TAG, "HTTP_EVENT_ON_HEADER"); break; + case HTTP_EVENT_ON_HEADERS_COMPLETE: + ESP_LOGI(TAG, "HTTP_EVENT_ON_HEADERS_COMPLETE"); + break; case HTTP_EVENT_ON_DATA: esp_rom_md5_update(&md5_context, evt->data, evt->data_len); break; diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c index 31b0f44f42..ee6ba6bce1 100644 --- a/components/esp_http_client/esp_http_client.c +++ b/components/esp_http_client/esp_http_client.c @@ -289,6 +289,8 @@ static int http_on_headers_complete(http_parser *parser) client->response->data_process = 0; ESP_LOGD(TAG, "http_on_headers_complete, status=%d, offset=%d, nread=%" PRId32, parser->status_code, client->response->data_offset, parser->nread); client->state = HTTP_STATE_RES_COMPLETE_HEADER; + http_dispatch_event(client, HTTP_EVENT_ON_HEADERS_COMPLETE, NULL, 0); + http_dispatch_event_to_event_loop(HTTP_EVENT_ON_HEADERS_COMPLETE, &client, sizeof(esp_http_client_handle_t)); if (client->connection_info.method == HTTP_METHOD_HEAD) { /* In a HTTP_RESPONSE parser returning '1' from on_headers_complete will tell the parser that it should not expect a body. This is used when receiving a response diff --git a/components/esp_http_client/include/esp_http_client.h b/components/esp_http_client/include/esp_http_client.h index 56f5ae4535..0bb6fdc223 100644 --- a/components/esp_http_client/include/esp_http_client.h +++ b/components/esp_http_client/include/esp_http_client.h @@ -39,6 +39,7 @@ typedef enum { HTTP_EVENT_HEADER_SENT = HTTP_EVENT_HEADERS_SENT, /*!< This header has been kept for backward compatibility and will be deprecated in future versions esp-idf */ HTTP_EVENT_ON_HEADER, /*!< Occurs when receiving each header sent from the server */ + HTTP_EVENT_ON_HEADERS_COMPLETE, /*!< Occurs when all headers are received on the client side */ HTTP_EVENT_ON_DATA, /*!< Occurs when receiving data from the server, possibly multiple portions of the packet */ HTTP_EVENT_ON_FINISH, /*!< Occurs when finish a HTTP session */ HTTP_EVENT_DISCONNECTED, /*!< The connection has been disconnected */ diff --git a/docs/en/api-reference/protocols/esp_http_client.rst b/docs/en/api-reference/protocols/esp_http_client.rst index 65ff08e93b..734b9fef04 100644 --- a/docs/en/api-reference/protocols/esp_http_client.rst +++ b/docs/en/api-reference/protocols/esp_http_client.rst @@ -126,14 +126,15 @@ Diagnostic information could be helpful to gain insights into a problem. In the Expected data types for different HTTP Client events in the event loop are as follows: - - HTTP_EVENT_ERROR : ``esp_http_client_handle_t`` - - HTTP_EVENT_ON_CONNECTED : ``esp_http_client_handle_t`` - - HTTP_EVENT_HEADERS_SENT : ``esp_http_client_handle_t`` - - HTTP_EVENT_ON_HEADER : ``esp_http_client_handle_t`` - - HTTP_EVENT_ON_DATA : ``esp_http_client_on_data_t`` - - HTTP_EVENT_ON_FINISH : ``esp_http_client_handle_t`` - - HTTP_EVENT_DISCONNECTED : ``esp_http_client_handle_t`` - - HTTP_EVENT_REDIRECT : ``esp_http_client_redirect_event_data_t`` + - HTTP_EVENT_ERROR : ``esp_http_client_handle_t`` + - HTTP_EVENT_ON_CONNECTED : ``esp_http_client_handle_t`` + - HTTP_EVENT_HEADERS_SENT : ``esp_http_client_handle_t`` + - HTTP_EVENT_ON_HEADER : ``esp_http_client_handle_t`` + - HTTP_EVENT_ON_HEADERS_COMPLETE: ``esp_http_client_handle_t`` + - HTTP_EVENT_ON_DATA : ``esp_http_client_on_data_t`` + - HTTP_EVENT_ON_FINISH : ``esp_http_client_handle_t`` + - HTTP_EVENT_DISCONNECTED : ``esp_http_client_handle_t`` + - HTTP_EVENT_REDIRECT : ``esp_http_client_redirect_event_data_t`` The :cpp:type:`esp_http_client_handle_t` received along with the event data will be valid until :cpp:enumerator:`HTTP_EVENT_DISCONNECTED ` is not received. This handle has been sent primarily to differentiate between different client connections and must not be used for any other purpose, as it may change based on client connection state. diff --git a/docs/zh_CN/api-reference/protocols/esp_http_client.rst b/docs/zh_CN/api-reference/protocols/esp_http_client.rst index 624df59958..b0cfb12634 100644 --- a/docs/zh_CN/api-reference/protocols/esp_http_client.rst +++ b/docs/zh_CN/api-reference/protocols/esp_http_client.rst @@ -126,14 +126,15 @@ ESP HTTP 客户端诊断信息 事件循环中不同 HTTP 客户端事件的预期数据类型如下所示: - - HTTP_EVENT_ERROR : ``esp_http_client_handle_t`` - - HTTP_EVENT_ON_CONNECTED : ``esp_http_client_handle_t`` - - HTTP_EVENT_HEADERS_SENT : ``esp_http_client_handle_t`` - - HTTP_EVENT_ON_HEADER : ``esp_http_client_handle_t`` - - HTTP_EVENT_ON_DATA : ``esp_http_client_on_data_t`` - - HTTP_EVENT_ON_FINISH : ``esp_http_client_handle_t`` - - HTTP_EVENT_DISCONNECTED : ``esp_http_client_handle_t`` - - HTTP_EVENT_REDIRECT : ``esp_http_client_redirect_event_data_t`` + - HTTP_EVENT_ERROR : ``esp_http_client_handle_t`` + - HTTP_EVENT_ON_CONNECTED : ``esp_http_client_handle_t`` + - HTTP_EVENT_HEADERS_SENT : ``esp_http_client_handle_t`` + - HTTP_EVENT_ON_HEADER : ``esp_http_client_handle_t`` + - HTTP_EVENT_ON_HEADERS_COMPLETE: ``esp_http_client_handle_t`` + - HTTP_EVENT_ON_DATA : ``esp_http_client_on_data_t`` + - HTTP_EVENT_ON_FINISH : ``esp_http_client_handle_t`` + - HTTP_EVENT_DISCONNECTED : ``esp_http_client_handle_t`` + - HTTP_EVENT_REDIRECT : ``esp_http_client_redirect_event_data_t`` 在无法接收到 :cpp:enumerator:`HTTP_EVENT_DISCONNECTED ` 之前,与事件数据一起接收到的 :cpp:type:`esp_http_client_handle_t` 将始终有效。这个句柄主要是为了区分不同的客户端连接,无法用于其他目的,因为它可能会随着客户端连接状态的变化而改变。 diff --git a/examples/protocols/dns_over_https/components/dns_over_https/dns_over_https.c b/examples/protocols/dns_over_https/components/dns_over_https/dns_over_https.c index 1a3f24d687..531be302e1 100644 --- a/examples/protocols/dns_over_https/components/dns_over_https/dns_over_https.c +++ b/examples/protocols/dns_over_https/components/dns_over_https/dns_over_https.c @@ -74,6 +74,9 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt) case HTTP_EVENT_ON_HEADER: ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); break; + case HTTP_EVENT_ON_HEADERS_COMPLETE: + ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADERS_COMPLETE"); + break; case HTTP_EVENT_ON_DATA: ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); /* Check if buffer is null, if yes, initialize it */ diff --git a/examples/protocols/esp_http_client/main/esp_http_client_example.c b/examples/protocols/esp_http_client/main/esp_http_client_example.c index dd3be26d5e..72b1aa847a 100644 --- a/examples/protocols/esp_http_client/main/esp_http_client_example.c +++ b/examples/protocols/esp_http_client/main/esp_http_client_example.c @@ -65,6 +65,9 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt) case HTTP_EVENT_ON_HEADER: ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); break; + case HTTP_EVENT_ON_HEADERS_COMPLETE: + ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADERS_COMPLETE"); + break; case HTTP_EVENT_ON_DATA: ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); // Clean the buffer in case of a new request diff --git a/examples/system/ota/partitions_ota/main/app_main.c b/examples/system/ota/partitions_ota/main/app_main.c index b77d85b0c0..02bd11518f 100644 --- a/examples/system/ota/partitions_ota/main/app_main.c +++ b/examples/system/ota/partitions_ota/main/app_main.c @@ -68,6 +68,9 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt) case HTTP_EVENT_ON_HEADER: ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); break; + case HTTP_EVENT_ON_HEADERS_COMPLETE: + ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADERS_COMPLETE"); + break; case HTTP_EVENT_ON_DATA: ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); break; diff --git a/examples/system/ota/simple_ota_example/main/simple_ota_example.c b/examples/system/ota/simple_ota_example/main/simple_ota_example.c index e3e8c732cb..bf4fdae9d2 100644 --- a/examples/system/ota/simple_ota_example/main/simple_ota_example.c +++ b/examples/system/ota/simple_ota_example/main/simple_ota_example.c @@ -60,6 +60,9 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt) case HTTP_EVENT_ON_HEADER: ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); break; + case HTTP_EVENT_ON_HEADERS_COMPLETE: + ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADERS_COMPLETE"); + break; case HTTP_EVENT_ON_DATA: ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); break;