From 5b9709eae629cb2d96506db04d4831a824d23560 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Krzywdzi=C5=84ski?= Date: Mon, 12 Jul 2021 10:26:41 +0200 Subject: [PATCH] http: Function to get Cookie value from request. --- .../esp_http_server/include/esp_http_server.h | 37 +++++++++ components/esp_http_server/src/httpd_parse.c | 81 +++++++++++++++++++ 2 files changed, 118 insertions(+) diff --git a/components/esp_http_server/include/esp_http_server.h b/components/esp_http_server/include/esp_http_server.h index d14a943c108c..e3fcfff46710 100644 --- a/components/esp_http_server/include/esp_http_server.h +++ b/components/esp_http_server/include/esp_http_server.h @@ -941,6 +941,43 @@ esp_err_t httpd_req_get_url_query_str(httpd_req_t *r, char *buf, size_t buf_len) */ esp_err_t httpd_query_key_value(const char *qry, const char *key, char *val, size_t val_size); +/** + * @brief Helper function to get a cookie value from a cookie + * string of the type "cookie1=val1; cookie2=val2" + * + * @note + * - If actual value size is greater than val_size, then the value is truncated, + * accompanied by truncation error as return value. + * + * @param[in] cookie_str Pointer to cookie string + * @param[in] key The key to be searched in the cookie string + * @param[out] val Pointer to the buffer into which the value will be copied if the key is found + * @param[in] val_size Size of the user buffer "val" + * + * @return + * - ESP_OK : Key is found in the cookie string and copied to buffer + * - ESP_ERR_NOT_FOUND : Key not found + * - ESP_ERR_INVALID_ARG : Null arguments + * - ESP_ERR_HTTPD_RESULT_TRUNC : Value string truncated + */ +esp_err_t httpd_cookie_key_value(const char *cookie_str, const char *key, char *val, size_t val_size); + +/** + * @brief Get the value string of a cookie value from the "Cookie" request headers by cookie name. + * + * @param[in] req Pointer to the HTTP request + * @param[in] cookie_name The cookie name to be searched in the request + * @param[out] val Pointer to the buffer into which the value of cookie will be copied if the cookie is found + * @param[in] val_size Size of the user buffer "val" + * + * @return + * - ESP_OK : Key is found in the cookie string and copied to buffer + * - ESP_ERR_NOT_FOUND : Key not found + * - ESP_ERR_INVALID_ARG : Null arguments + * - ESP_ERR_HTTPD_RESULT_TRUNC : Value string truncated + */ +esp_err_t httpd_req_get_cookie_val(httpd_req_t *req, const char *cookie_name, char *val, size_t val_size); + /** * @brief Test if a URI matches the given wildcard template. * diff --git a/components/esp_http_server/src/httpd_parse.c b/components/esp_http_server/src/httpd_parse.c index 9fe790759136..df8822585d30 100644 --- a/components/esp_http_server/src/httpd_parse.c +++ b/components/esp_http_server/src/httpd_parse.c @@ -1070,3 +1070,84 @@ esp_err_t httpd_req_get_hdr_value_str(httpd_req_t *r, const char *field, char *v } return ESP_ERR_NOT_FOUND; } + +/* Helper function to get a cookie value from a cookie string of the type "cookie1=val1; cookie2=val2" */ +esp_err_t httpd_cookie_key_value(const char *cookie_str, const char *key, char *val, size_t val_size) +{ + if(cookie_str == NULL || key == NULL || val == NULL) { + return ESP_ERR_INVALID_ARG; + } + + const char *cookie_ptr = cookie_str; + const size_t buf_len = val_size; + + while(strlen(cookie_ptr)) { + /* Search for the '=' character. Else, it would mean + * that the parameter is invalid */ + const char *val_ptr = strchr(cookie_ptr, '='); + if(!val_ptr) { + break; + } + size_t offset = val_ptr - cookie_ptr; + + /* If the key, does not match, continue searching. + * Compare lengths first as key from cookie string is not + * null terminated (has '=' in the end) */ + if((offset != strlen(key)) || (strncmp(cookie_ptr, key, offset))) { + /* Get the name=val string. Multiple name=value pairs + * are separated by '; ' */ + cookie_ptr = strchr(val_ptr, ' '); + if(!cookie_ptr) { + break; + } + cookie_ptr++; + continue; + } + + /* Locate start of next query */ + cookie_ptr = strchr(++val_ptr, ';'); + /* Or this could be the last query, in which + * case get to the end of query string */ + if(!cookie_ptr) { + cookie_ptr = val_ptr + strlen(val_ptr); + } + + /* Update value length, including one byte for null */ + val_size = cookie_ptr - val_ptr + 1; + + /* Copy value to the caller's buffer. */ + strlcpy(val, val_ptr, MIN(val_size, buf_len)); + + /* If buffer length is smaller than needed, return truncation error */ + if(buf_len < val_size) { + return ESP_ERR_HTTPD_RESULT_TRUNC; + } + return ESP_OK; + } + ESP_LOGD(TAG, LOG_FMT("cookie %s not found"), key); + return ESP_ERR_NOT_FOUND; +} + +/* Get the value of a cookie from the request headers */ +esp_err_t httpd_req_get_cookie_val(httpd_req_t *req, const char *cookie_name, char *val, size_t val_size) +{ + esp_err_t ret; + size_t hdr_len_cookie = httpd_req_get_hdr_value_len(req, "Cookie"); + char *cookie_str; + + if(hdr_len_cookie <= 0) { + return ESP_ERR_NOT_FOUND; + } + cookie_str = malloc(hdr_len_cookie + 1); + + if(httpd_req_get_hdr_value_str(req, "Cookie", cookie_str, hdr_len_cookie + 1) != ESP_OK) { + ESP_LOGW(TAG, "Not Found Cookie in header uri:[%s]", req->uri); + free(cookie_str); + return ESP_ERR_NOT_FOUND; + } + + ret = httpd_cookie_key_value(cookie_str, cookie_name, val, val_size); + free(cookie_str); + return ret; + +}