diff --git a/components/esp_http_server/include/esp_http_server.h b/components/esp_http_server/include/esp_http_server.h index d834982f0a..6bd69f4b5c 100644 --- a/components/esp_http_server/include/esp_http_server.h +++ b/components/esp_http_server/include/esp_http_server.h @@ -1813,6 +1813,44 @@ esp_err_t httpd_ws_send_data_async(httpd_handle_t handle, int socket, httpd_ws_f * @} */ +/** + * @brief Get the length of the raw request data received from the client. + * + * @param[in] req Current request + * @return + * - 0 : If req is NULL + * - size_t : The length of the buffer containing raw HTTP request data + */ +size_t httpd_get_raw_req_data_len(httpd_req_t *req); + +/** + * @brief Get the raw HTTP request data received from the client. + * + * NOTE - This function returns different data for different http server states. + * 1. HTTP_SERVER_EVENT_ON_CONNECTED - Returns the data containing information related to URI and headers. + * 2. HTTP_SERVER_EVENT_ON_HEADER - Returns the data containing information related to only headers. + * 3. HTTP_SERVER_EVENT_ON_DATA - Returns the data containing information related to only headers. + * 4. HTTP_SERVER_EVENT_SENT_DATA - Returns the data containing information related to only headers. + * 5. HTTP_SERVER_EVENT_DISCONNECTED - Returns the data containing information related to only headers. + * 6. HTTP_SERVER_EVENT_STOP - Returns the data containing information related to only headers. + * + * @param[in] req Current request + * @param[out] buf Buffer to store the raw request data + * @param[in] buf_len The length of the buffer. + * @return + * - ESP_OK : On successful copy of raw request data + * - ESP_ERR_INVALID_ARG : If req or buf is NULL, or buf_len is 0 + */ +esp_err_t httpd_get_raw_req_data(httpd_req_t *req, char *buf, size_t buf_len); + +/** + * @brief Get the HTTPD server state + * + * @param[in] handle Handle to server returned by httpd_start + * @return HTTPD server state + */ +esp_http_server_event_id_t httpd_get_server_state(httpd_handle_t handle); + #ifdef __cplusplus } #endif diff --git a/components/esp_http_server/src/esp_httpd_priv.h b/components/esp_http_server/src/esp_httpd_priv.h index f226c074f5..499d5f044e 100644 --- a/components/esp_http_server/src/esp_httpd_priv.h +++ b/components/esp_http_server/src/esp_httpd_priv.h @@ -127,6 +127,7 @@ struct httpd_data { struct httpd_req hd_req; /*!< The current HTTPD request */ struct httpd_req_aux hd_req_aux; /*!< Additional data about the HTTPD request kept unexposed */ uint64_t lru_counter; /*!< LRU counter */ + esp_http_server_event_id_t http_server_state; /*!< HTTPD server state */ /* Array of registered error handler functions */ httpd_err_handler_func_t *err_handler_fns; diff --git a/components/esp_http_server/src/httpd_main.c b/components/esp_http_server/src/httpd_main.c index fd434e87ae..bc85c9e470 100644 --- a/components/esp_http_server/src/httpd_main.c +++ b/components/esp_http_server/src/httpd_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -126,6 +126,7 @@ static esp_err_t httpd_accept_conn(struct httpd_data *hd, int listen_fd) goto exit; } ESP_LOGD(TAG, LOG_FMT("complete")); + hd->http_server_state = HTTP_SERVER_EVENT_ON_CONNECTED; esp_http_server_dispatch_event(HTTP_SERVER_EVENT_ON_CONNECTED, &new_fd, sizeof(int)); return ESP_OK; exit: @@ -539,6 +540,7 @@ esp_err_t httpd_start(httpd_handle_t *handle, const httpd_config_t *config) } *handle = (httpd_handle_t)hd; + hd->http_server_state = HTTP_SERVER_EVENT_START; esp_http_server_dispatch_event(HTTP_SERVER_EVENT_START, NULL, 0); return ESP_OK; @@ -593,3 +595,12 @@ esp_err_t httpd_stop(httpd_handle_t handle) esp_http_server_dispatch_event(HTTP_SERVER_EVENT_STOP, NULL, 0); return ESP_OK; } + +esp_http_server_event_id_t httpd_get_server_state(httpd_handle_t handle) +{ + struct httpd_data *hd = (struct httpd_data *) handle; + if (hd == NULL) { + return HTTP_SERVER_EVENT_ERROR; + } + return hd->http_server_state; +} diff --git a/components/esp_http_server/src/httpd_parse.c b/components/esp_http_server/src/httpd_parse.c index 2fb7504201..357480790c 100644 --- a/components/esp_http_server/src/httpd_parse.c +++ b/components/esp_http_server/src/httpd_parse.c @@ -408,6 +408,8 @@ static esp_err_t cb_headers_complete(http_parser *parser) parser_data->status = PARSING_BODY; ra->remaining_len = r->content_len; + struct httpd_data *hd = (struct httpd_data *) r->handle; + hd->http_server_state = HTTP_SERVER_EVENT_ON_HEADER; esp_http_server_dispatch_event(HTTP_SERVER_EVENT_ON_HEADER, &(ra->sd->fd), sizeof(int)); return ESP_OK; } @@ -1209,3 +1211,44 @@ esp_err_t httpd_req_get_cookie_val(httpd_req_t *req, const char *cookie_name, ch return ret; } + +/* Get the length of the raw request data received from the client. + */ +size_t httpd_get_raw_req_data_len(httpd_req_t *req) +{ + if (req == NULL) { + return 0; + } + struct httpd_req_aux *ra = req->aux; + return ra->scratch_cur_size; +} + +/* Get the raw request data, which contains the raw HTTP request headers and + * URI related information. Internally, the httpd_parse.c file uses a scratch buffer + * to store the original HTTP request data exactly as received from the client. + * This function returns the contents of this scratch buffer. + * + * NOTE - This function returns different data for different http server states. + * 1. HTTP_SERVER_EVENT_ON_CONNECTED - Returns the data containing information related to URI and headers. + * 2. HTTP_SERVER_EVENT_ON_HEADER - Returns the data containing information related to only headers. + * 3. HTTP_SERVER_EVENT_ON_DATA - Returns the data containing information related to only headers. + * 4. HTTP_SERVER_EVENT_SENT_DATA - Returns the data containing information related to only headers. + * 5. HTTP_SERVER_EVENT_DISCONNECTED - Returns the data containing information related to only headers. + * 6. HTTP_SERVER_EVENT_STOP - Returns the data containing information related to only headers. + */ +esp_err_t httpd_get_raw_req_data(httpd_req_t *req, char *buf, size_t buf_len) +{ + if (req == NULL || buf == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (buf_len == 0) { + return ESP_ERR_INVALID_ARG; + } + if (req->aux == NULL) { + ESP_LOGW(TAG, "Request auxiliary data is NULL for URI: [%s]", req->uri ? req->uri : "(null)"); + return ESP_ERR_INVALID_ARG; + } + struct httpd_req_aux *ra = req->aux; + memcpy(buf, ra->scratch, buf_len); + return ESP_OK; +} diff --git a/components/esp_http_server/src/httpd_sess.c b/components/esp_http_server/src/httpd_sess.c index ac03edf8d1..104b334337 100644 --- a/components/esp_http_server/src/httpd_sess.c +++ b/components/esp_http_server/src/httpd_sess.c @@ -146,6 +146,7 @@ static void httpd_sess_close(void *arg) } sock_db->lru_socket = false; struct httpd_data *hd = (struct httpd_data *) sock_db->handle; + hd->http_server_state = HTTP_SERVER_EVENT_DISCONNECTED; httpd_sess_delete(hd, sock_db); } @@ -374,6 +375,7 @@ void httpd_sess_delete(struct httpd_data *hd, struct sock_db *session) } else { close(session->fd); } + hd->http_server_state = HTTP_SERVER_EVENT_DISCONNECTED; esp_http_server_dispatch_event(HTTP_SERVER_EVENT_DISCONNECTED, &session->fd, sizeof(int)); // clear all contexts diff --git a/components/esp_http_server/src/httpd_txrx.c b/components/esp_http_server/src/httpd_txrx.c index 0393197cc4..e291cea3fc 100644 --- a/components/esp_http_server/src/httpd_txrx.c +++ b/components/esp_http_server/src/httpd_txrx.c @@ -294,6 +294,8 @@ esp_err_t httpd_resp_send(httpd_req_t *r, const char *buf, ssize_t buf_len) if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) { return ESP_ERR_HTTPD_RESP_SEND; } + struct httpd_data *hd = (struct httpd_data *) r->handle; + hd->http_server_state = HTTP_SERVER_EVENT_HEADERS_SENT; esp_http_server_dispatch_event(HTTP_SERVER_EVENT_HEADERS_SENT, &(ra->sd->fd), sizeof(int)); /* Sending content */ @@ -306,6 +308,7 @@ esp_err_t httpd_resp_send(httpd_req_t *r, const char *buf, ssize_t buf_len) .fd = ra->sd->fd, .data_len = buf_len, }; + hd->http_server_state = HTTP_SERVER_EVENT_SENT_DATA; esp_http_server_dispatch_event(HTTP_SERVER_EVENT_SENT_DATA, &evt_data, sizeof(esp_http_server_event_data)); return ESP_OK; } @@ -325,6 +328,7 @@ esp_err_t httpd_resp_send_chunk(httpd_req_t *r, const char *buf, ssize_t buf_len } struct httpd_req_aux *ra = r->aux; + struct httpd_data *hd = (struct httpd_data *) r->handle; const char *httpd_chunked_hdr_str = "HTTP/1.1 %s\r\nContent-Type: %s\r\nTransfer-Encoding: chunked\r\n"; const char *colon_separator = ": "; const char *cr_lf_seperator = "\r\n"; @@ -404,6 +408,7 @@ esp_err_t httpd_resp_send_chunk(httpd_req_t *r, const char *buf, ssize_t buf_len .fd = ra->sd->fd, .data_len = buf_len, }; + hd->http_server_state = HTTP_SERVER_EVENT_SENT_DATA; esp_http_server_dispatch_event(HTTP_SERVER_EVENT_SENT_DATA, &evt_data, sizeof(esp_http_server_event_data)); return ESP_OK; @@ -613,6 +618,8 @@ int httpd_req_recv(httpd_req_t *r, char *buf, size_t buf_len) } ra->remaining_len -= ret; ESP_LOGD(TAG, LOG_FMT("received length = %d"), ret); + struct httpd_data *hd = (struct httpd_data *) r->handle; + hd->http_server_state = HTTP_SERVER_EVENT_ON_DATA; esp_http_server_event_data evt_data = { .fd = ra->sd->fd, .data_len = ret,