|
|
@@ -22,6 +22,7 @@
|
|
|
#include "esp_http_client.h"
|
|
|
|
|
|
#define MAX_HTTP_RECV_BUFFER 512
|
|
|
+#define MAX_HTTP_OUTPUT_BUFFER 2048
|
|
|
static const char *TAG = "HTTP_CLIENT";
|
|
|
|
|
|
/* Root cert for howsmyssl.com, taken from howsmyssl_com_root_cert.pem
|
|
|
@@ -39,6 +40,8 @@ extern const char howsmyssl_com_root_cert_pem_end[] asm("_binary_howsmyssl_com
|
|
|
|
|
|
esp_err_t _http_event_handler(esp_http_client_event_t *evt)
|
|
|
{
|
|
|
+ static char *output_buffer; // Buffer to store response of http request from event handler
|
|
|
+ static int output_len; // Stores number of bytes read
|
|
|
switch(evt->event_id) {
|
|
|
case HTTP_EVENT_ERROR:
|
|
|
ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
|
|
|
@@ -54,20 +57,49 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt)
|
|
|
break;
|
|
|
case HTTP_EVENT_ON_DATA:
|
|
|
ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
|
|
|
+ /*
|
|
|
+ * Check for chunked encoding is added as the URL for chunked encoding used in this example returns binary data.
|
|
|
+ * However, event handler can also be used in case chunked encoding is used.
|
|
|
+ */
|
|
|
if (!esp_http_client_is_chunked_response(evt->client)) {
|
|
|
- // Write out data
|
|
|
- // printf("%.*s", evt->data_len, (char*)evt->data);
|
|
|
+ // If user_data buffer is configured, copy the response into the buffer
|
|
|
+ if (evt->user_data) {
|
|
|
+ memcpy(evt->user_data + output_len, evt->data, evt->data_len);
|
|
|
+ } else {
|
|
|
+ if (output_buffer == NULL) {
|
|
|
+ output_buffer = (char *) malloc(esp_http_client_get_content_length(evt->client));
|
|
|
+ output_len = 0;
|
|
|
+ if (output_buffer == NULL) {
|
|
|
+ ESP_LOGE(TAG, "Failed to allocate memory for output buffer");
|
|
|
+ return ESP_FAIL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ memcpy(output_buffer + output_len, evt->data, evt->data_len);
|
|
|
+ }
|
|
|
+ output_len += evt->data_len;
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
case HTTP_EVENT_ON_FINISH:
|
|
|
ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
|
|
|
+ if (output_buffer != NULL) {
|
|
|
+ // Response is accumulated in output_buffer. Uncomment the below line to print the accumulated response
|
|
|
+ // ESP_LOG_BUFFER_HEX(TAG, output_buffer, output_len);
|
|
|
+ free(output_buffer);
|
|
|
+ output_buffer = NULL;
|
|
|
+ output_len = 0;
|
|
|
+ }
|
|
|
break;
|
|
|
case HTTP_EVENT_DISCONNECTED:
|
|
|
ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
|
|
|
int mbedtls_err = 0;
|
|
|
esp_err_t err = esp_tls_get_and_clear_last_error(evt->data, &mbedtls_err, NULL);
|
|
|
if (err != 0) {
|
|
|
+ if (output_buffer != NULL) {
|
|
|
+ free(output_buffer);
|
|
|
+ output_buffer = NULL;
|
|
|
+ output_len = 0;
|
|
|
+ }
|
|
|
ESP_LOGI(TAG, "Last esp error code: 0x%x", err);
|
|
|
ESP_LOGI(TAG, "Last mbedtls failure: 0x%x", mbedtls_err);
|
|
|
}
|
|
|
@@ -78,9 +110,11 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt)
|
|
|
|
|
|
static void http_rest_with_url(void)
|
|
|
{
|
|
|
+ char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0};
|
|
|
esp_http_client_config_t config = {
|
|
|
.url = "http://httpbin.org/get",
|
|
|
.event_handler = _http_event_handler,
|
|
|
+ .user_data = local_response_buffer, // Pass address of local buffer to get response
|
|
|
};
|
|
|
esp_http_client_handle_t client = esp_http_client_init(&config);
|
|
|
|
|
|
@@ -93,11 +127,13 @@ static void http_rest_with_url(void)
|
|
|
} else {
|
|
|
ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
|
|
|
}
|
|
|
+ ESP_LOG_BUFFER_HEX(TAG, local_response_buffer, strlen(local_response_buffer));
|
|
|
|
|
|
// POST
|
|
|
- const char *post_data = "field1=value1&field2=value2";
|
|
|
+ const char *post_data = "{\"field1\":\"value1\"}";
|
|
|
esp_http_client_set_url(client, "http://httpbin.org/post");
|
|
|
esp_http_client_set_method(client, HTTP_METHOD_POST);
|
|
|
+ esp_http_client_set_header(client, "Content-Type", "application/json");
|
|
|
esp_http_client_set_post_field(client, post_data, strlen(post_data));
|
|
|
err = esp_http_client_perform(client);
|
|
|
if (err == ESP_OK) {
|
|
|
@@ -246,7 +282,7 @@ static void http_rest_with_hostname_path(void)
|
|
|
esp_http_client_cleanup(client);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+#if CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH
|
|
|
static void http_auth_basic(void)
|
|
|
{
|
|
|
esp_http_client_config_t config = {
|
|
|
@@ -285,6 +321,7 @@ static void http_auth_basic_redirect(void)
|
|
|
}
|
|
|
esp_http_client_cleanup(client);
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
static void http_auth_digest(void)
|
|
|
{
|
|
|
@@ -433,7 +470,6 @@ static void http_perform_as_stream_reader(void)
|
|
|
}
|
|
|
esp_http_client_config_t config = {
|
|
|
.url = "http://httpbin.org/get",
|
|
|
- .event_handler = _http_event_handler,
|
|
|
};
|
|
|
esp_http_client_handle_t client = esp_http_client_init(&config);
|
|
|
esp_err_t err;
|
|
|
@@ -511,13 +547,78 @@ static void https_with_invalid_url(void)
|
|
|
esp_http_client_cleanup(client);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * http_native_request() demonstrates use of low level APIs to connect to a server,
|
|
|
+ * make a http request and read response. Event handler is not used in this case.
|
|
|
+ * Note: This approach should only be used in case use of low level APIs is required.
|
|
|
+ * The easiest way is to use esp_http_perform()
|
|
|
+ */
|
|
|
+static void http_native_request(void)
|
|
|
+{
|
|
|
+ char output_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0}; // Buffer to store response of http request
|
|
|
+ int content_length = 0;
|
|
|
+ esp_http_client_config_t config = {
|
|
|
+ .url = "http://httpbin.org/get",
|
|
|
+ };
|
|
|
+ esp_http_client_handle_t client = esp_http_client_init(&config);
|
|
|
+
|
|
|
+ // GET Request
|
|
|
+ esp_http_client_set_method(client, HTTP_METHOD_GET);
|
|
|
+ esp_err_t err = esp_http_client_open(client, 0);
|
|
|
+ if (err != ESP_OK) {
|
|
|
+ ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
|
|
|
+ } else {
|
|
|
+ content_length = esp_http_client_fetch_headers(client);
|
|
|
+ if (content_length < 0) {
|
|
|
+ ESP_LOGE(TAG, "HTTP client fetch headers failed");
|
|
|
+ } else {
|
|
|
+ int data_read = esp_http_client_read_response(client, output_buffer, MAX_HTTP_OUTPUT_BUFFER);
|
|
|
+ if (data_read >= 0) {
|
|
|
+ ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d",
|
|
|
+ esp_http_client_get_status_code(client),
|
|
|
+ esp_http_client_get_content_length(client));
|
|
|
+ ESP_LOG_BUFFER_HEX(TAG, output_buffer, strlen(output_buffer));
|
|
|
+ } else {
|
|
|
+ ESP_LOGE(TAG, "Failed to read response");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ esp_http_client_close(client);
|
|
|
+
|
|
|
+ // POST Request
|
|
|
+ const char *post_data = "{\"field1\":\"value1\"}";
|
|
|
+ esp_http_client_set_url(client, "http://httpbin.org/post");
|
|
|
+ esp_http_client_set_method(client, HTTP_METHOD_POST);
|
|
|
+ esp_http_client_set_header(client, "Content-Type", "application/json");
|
|
|
+ err = esp_http_client_open(client, strlen(post_data));
|
|
|
+ if (err != ESP_OK) {
|
|
|
+ ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
|
|
|
+ } else {
|
|
|
+ int wlen = esp_http_client_write(client, post_data, strlen(post_data));
|
|
|
+ if (wlen < 0) {
|
|
|
+ ESP_LOGE(TAG, "Write failed");
|
|
|
+ }
|
|
|
+ int data_read = esp_http_client_read_response(client, output_buffer, MAX_HTTP_OUTPUT_BUFFER);
|
|
|
+ if (data_read >= 0) {
|
|
|
+ ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d",
|
|
|
+ esp_http_client_get_status_code(client),
|
|
|
+ esp_http_client_get_content_length(client));
|
|
|
+ ESP_LOG_BUFFER_HEX(TAG, output_buffer, strlen(output_buffer));
|
|
|
+ } else {
|
|
|
+ ESP_LOGE(TAG, "Failed to read response");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ esp_http_client_cleanup(client);
|
|
|
+}
|
|
|
|
|
|
static void http_test_task(void *pvParameters)
|
|
|
{
|
|
|
http_rest_with_url();
|
|
|
http_rest_with_hostname_path();
|
|
|
+#if CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH
|
|
|
http_auth_basic();
|
|
|
http_auth_basic_redirect();
|
|
|
+#endif
|
|
|
http_auth_digest();
|
|
|
http_relative_redirect();
|
|
|
http_absolute_redirect();
|
|
|
@@ -528,6 +629,7 @@ static void http_test_task(void *pvParameters)
|
|
|
http_perform_as_stream_reader();
|
|
|
https_async();
|
|
|
https_with_invalid_url();
|
|
|
+ http_native_request();
|
|
|
|
|
|
ESP_LOGI(TAG, "Finish http example");
|
|
|
vTaskDelete(NULL);
|