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;
+
+}