http_handlers.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #include "http_handlers.h"
  2. #include "esp_http_client.h"
  3. #include "esp_log.h"
  4. #include "esp_tls.h"
  5. #include "tools.h"
  6. #include <sys/param.h>
  7. #if CONFIG_WITH_METRICS
  8. static const char* TAG = "metrics_http";
  9. static char* output_buffer; // Buffer to store response of http request from
  10. // event handler
  11. static int output_len = 0; // Stores number of bytes read
  12. #define MAX_HTTP_OUTPUT_BUFFER 2048
  13. // Common function signature for event handlers
  14. typedef void (*HttpEventHandler)(esp_http_client_event_t* evt);
  15. static void handle_http_error(esp_http_client_event_t* evt) { ESP_LOGV(TAG, "ERROR"); }
  16. static void handle_http_connected(esp_http_client_event_t* evt) {
  17. ESP_LOGV(TAG, "ON_CONNECTED");
  18. }
  19. static void handle_http_header_sent(esp_http_client_event_t* evt) {
  20. ESP_LOGV(TAG, "HEADER_SENT");
  21. }
  22. static void handle_http_on_header(esp_http_client_event_t* evt) {
  23. ESP_LOGV(TAG, "ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
  24. }
  25. static void handle_http_on_data(esp_http_client_event_t* evt) {
  26. ESP_LOGV(TAG, "ON_DATA, len=%d", evt->data_len);
  27. ESP_LOGV(TAG, "ON_DATA, len=%d", evt->data_len);
  28. // Clean the buffer in case of a new request
  29. if (output_len == 0 && evt->user_data) {
  30. // we are just starting to copy the output data into the use
  31. ESP_LOGV(TAG, "Resetting buffer");
  32. memset(evt->user_data, 0, MAX_HTTP_OUTPUT_BUFFER);
  33. }
  34. /*
  35. * Check for chunked encoding is added as the URL for chunked encoding used in this example
  36. * returns binary data. However, event handler can also be used in case chunked encoding is
  37. * used.
  38. */
  39. // If user_data buffer is configured, copy the response into the buffer
  40. int copy_len = 0;
  41. if (evt->user_data) {
  42. ESP_LOGV(TAG, "Not Chunked response, with user data");
  43. // The last byte in evt->user_data is kept for the NULL character in
  44. // case of out-of-bound access.
  45. copy_len = MIN(evt->data_len, (MAX_HTTP_OUTPUT_BUFFER - output_len));
  46. if (copy_len) {
  47. memcpy(evt->user_data + output_len, evt->data, copy_len);
  48. }
  49. } else {
  50. int content_len = esp_http_client_get_content_length(evt->client);
  51. if (esp_http_client_is_chunked_response(evt->client)) {
  52. esp_http_client_get_chunk_length(evt->client, &content_len);
  53. }
  54. if (output_buffer == NULL) {
  55. // We initialize output_buffer with 0 because it is used by
  56. // strlen() and similar functions therefore should be null
  57. // terminated.
  58. size_t len=(content_len + 1) * sizeof(char);
  59. ESP_LOGV(TAG, "Init buffer %d",len);
  60. output_buffer = (char*)malloc_init_external(len);
  61. output_len = 0;
  62. if (output_buffer == NULL) {
  63. ESP_LOGE(TAG, "Buffer alloc failed.");
  64. return;
  65. }
  66. }
  67. copy_len = MIN(evt->data_len, (content_len - output_len));
  68. if (copy_len) {
  69. memcpy(output_buffer + output_len, evt->data, copy_len);
  70. }
  71. }
  72. output_len += copy_len;
  73. }
  74. static void handle_http_on_finish(esp_http_client_event_t* evt) {
  75. ESP_LOGD(TAG, "ON_FINISH");
  76. if (output_buffer != NULL) {
  77. ESP_LOGV(TAG, "Response: %s", output_buffer);
  78. free(output_buffer);
  79. output_buffer = NULL;
  80. }
  81. output_len = 0;
  82. }
  83. static void handle_http_disconnected(esp_http_client_event_t* evt) {
  84. ESP_LOGI(TAG, "DISCONNECTED");
  85. int mbedtls_err = 0;
  86. esp_err_t err =
  87. esp_tls_get_and_clear_last_error((esp_tls_error_handle_t)evt->data, &mbedtls_err, NULL);
  88. if (err != 0) {
  89. ESP_LOGI(TAG, "Last error : %s", esp_err_to_name(err));
  90. ESP_LOGI(TAG, "Last mbedtls err 0x%x", mbedtls_err);
  91. }
  92. if (output_buffer != NULL) {
  93. free(output_buffer);
  94. output_buffer = NULL;
  95. }
  96. output_len = 0;
  97. }
  98. static const HttpEventHandler eventHandlers[] = {
  99. handle_http_error, // HTTP_EVENT_ERROR
  100. handle_http_connected, // HTTP_EVENT_ON_CONNECTED
  101. handle_http_header_sent, // HTTP_EVENT_HEADERS_SENT
  102. handle_http_header_sent, // HTTP_EVENT_HEADER_SENT (alias for HTTP_EVENT_HEADERS_SENT)
  103. handle_http_on_header, // HTTP_EVENT_ON_HEADER
  104. handle_http_on_data, // HTTP_EVENT_ON_DATA
  105. handle_http_on_finish, // HTTP_EVENT_ON_FINISH
  106. handle_http_disconnected // HTTP_EVENT_DISCONNECTED
  107. };
  108. esp_err_t metrics_http_event_handler(esp_http_client_event_t* evt) {
  109. if (evt->event_id < 0 || evt->event_id >= sizeof(eventHandlers) / sizeof(eventHandlers[0])) {
  110. ESP_LOGE(TAG, "Invalid event ID: %d", evt->event_id);
  111. return ESP_FAIL;
  112. }
  113. eventHandlers[evt->event_id](evt);
  114. return ESP_OK;
  115. }
  116. int metrics_http_post_request(const char* payload, const char* url) {
  117. int status_code = 0;
  118. esp_http_client_config_t config = {.url = url,
  119. .disable_auto_redirect = false,
  120. .event_handler = metrics_http_event_handler,
  121. .transport_type = HTTP_TRANSPORT_OVER_SSL,
  122. .user_data = NULL, // local_response_buffer, // Pass address of
  123. // local buffer to get response
  124. .skip_cert_common_name_check = true
  125. };
  126. esp_http_client_handle_t client = esp_http_client_init(&config);
  127. esp_err_t err = esp_http_client_set_method(client, HTTP_METHOD_POST);
  128. if (err == ESP_OK) {
  129. err = esp_http_client_set_header(client, "Content-Type", "application/json");
  130. }
  131. if (err == ESP_OK) {
  132. ESP_LOGV(TAG, "Setting payload: %s", payload);
  133. err = esp_http_client_set_post_field(client, payload, strlen(payload));
  134. }
  135. if (err == ESP_OK) {
  136. err = esp_http_client_perform(client);
  137. }
  138. if (err == ESP_OK) {
  139. status_code = esp_http_client_get_status_code(client);
  140. ESP_LOGD(TAG, "metrics call Status = %d, content_length = %d",
  141. esp_http_client_get_status_code(client), esp_http_client_get_content_length(client));
  142. } else {
  143. status_code = 500;
  144. ESP_LOGW(TAG, "metrics call Status failed: %s", esp_err_to_name(err));
  145. }
  146. esp_http_client_cleanup(client);
  147. return status_code;
  148. }
  149. #endif