Merge branch 'feature/esp_http_client_add_example' into 'master'
Add example to demonstrate use of low level APIs in http client Closes IDFGH-2773 See merge request espressif/esp-idf!7832
This commit is contained in:
commit
4e0e15631d
3 changed files with 134 additions and 5 deletions
|
@ -1315,3 +1315,16 @@ void esp_http_client_add_auth(esp_http_client_handle_t client)
|
||||||
ESP_LOGW(TAG, "This request requires authentication, but does not provide header information for that");
|
ESP_LOGW(TAG, "This request requires authentication, but does not provide header information for that");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int esp_http_client_read_response(esp_http_client_handle_t client, char *buffer, int len)
|
||||||
|
{
|
||||||
|
int read_len = 0;
|
||||||
|
while (read_len < len) {
|
||||||
|
int data_read = esp_http_client_read(client, buffer + read_len, len - read_len);
|
||||||
|
if (data_read <= 0) {
|
||||||
|
return read_len;
|
||||||
|
}
|
||||||
|
read_len += data_read;
|
||||||
|
}
|
||||||
|
return read_len;
|
||||||
|
}
|
||||||
|
|
|
@ -497,6 +497,20 @@ void esp_http_client_add_auth(esp_http_client_handle_t client);
|
||||||
*/
|
*/
|
||||||
bool esp_http_client_is_complete_data_received(esp_http_client_handle_t client);
|
bool esp_http_client_is_complete_data_received(esp_http_client_handle_t client);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper API to read larger data chunks
|
||||||
|
* This is a helper API which internally calls `esp_http_client_read` multiple times till the end of data is reached or till the buffer gets full.
|
||||||
|
*
|
||||||
|
* @param[in] client The esp_http_client handle
|
||||||
|
* @param buffer The buffer
|
||||||
|
* @param[in] len The buffer length
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - Length of data was read
|
||||||
|
*/
|
||||||
|
|
||||||
|
int esp_http_client_read_response(esp_http_client_handle_t client, char *buffer, int len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "esp_http_client.h"
|
#include "esp_http_client.h"
|
||||||
|
|
||||||
#define MAX_HTTP_RECV_BUFFER 512
|
#define MAX_HTTP_RECV_BUFFER 512
|
||||||
|
#define MAX_HTTP_OUTPUT_BUFFER 2048
|
||||||
static const char *TAG = "HTTP_CLIENT";
|
static const char *TAG = "HTTP_CLIENT";
|
||||||
|
|
||||||
/* Root cert for howsmyssl.com, taken from howsmyssl_com_root_cert.pem
|
/* 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)
|
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) {
|
switch(evt->event_id) {
|
||||||
case HTTP_EVENT_ERROR:
|
case HTTP_EVENT_ERROR:
|
||||||
ESP_LOGD(TAG, "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;
|
break;
|
||||||
case HTTP_EVENT_ON_DATA:
|
case HTTP_EVENT_ON_DATA:
|
||||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
|
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)) {
|
if (!esp_http_client_is_chunked_response(evt->client)) {
|
||||||
// Write out data
|
// If user_data buffer is configured, copy the response into the buffer
|
||||||
// printf("%.*s", evt->data_len, (char*)evt->data);
|
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;
|
break;
|
||||||
case HTTP_EVENT_ON_FINISH:
|
case HTTP_EVENT_ON_FINISH:
|
||||||
ESP_LOGD(TAG, "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;
|
break;
|
||||||
case HTTP_EVENT_DISCONNECTED:
|
case HTTP_EVENT_DISCONNECTED:
|
||||||
ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
|
ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
|
||||||
int mbedtls_err = 0;
|
int mbedtls_err = 0;
|
||||||
esp_err_t err = esp_tls_get_and_clear_last_error(evt->data, &mbedtls_err, NULL);
|
esp_err_t err = esp_tls_get_and_clear_last_error(evt->data, &mbedtls_err, NULL);
|
||||||
if (err != 0) {
|
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 esp error code: 0x%x", err);
|
||||||
ESP_LOGI(TAG, "Last mbedtls failure: 0x%x", mbedtls_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)
|
static void http_rest_with_url(void)
|
||||||
{
|
{
|
||||||
|
char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0};
|
||||||
esp_http_client_config_t config = {
|
esp_http_client_config_t config = {
|
||||||
.url = "http://httpbin.org/get",
|
.url = "http://httpbin.org/get",
|
||||||
.event_handler = _http_event_handler,
|
.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);
|
esp_http_client_handle_t client = esp_http_client_init(&config);
|
||||||
|
|
||||||
|
@ -93,11 +127,13 @@ static void http_rest_with_url(void)
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
|
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
|
// 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_url(client, "http://httpbin.org/post");
|
||||||
esp_http_client_set_method(client, HTTP_METHOD_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));
|
esp_http_client_set_post_field(client, post_data, strlen(post_data));
|
||||||
err = esp_http_client_perform(client);
|
err = esp_http_client_perform(client);
|
||||||
if (err == ESP_OK) {
|
if (err == ESP_OK) {
|
||||||
|
@ -246,7 +282,7 @@ static void http_rest_with_hostname_path(void)
|
||||||
esp_http_client_cleanup(client);
|
esp_http_client_cleanup(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH
|
||||||
static void http_auth_basic(void)
|
static void http_auth_basic(void)
|
||||||
{
|
{
|
||||||
esp_http_client_config_t config = {
|
esp_http_client_config_t config = {
|
||||||
|
@ -285,6 +321,7 @@ static void http_auth_basic_redirect(void)
|
||||||
}
|
}
|
||||||
esp_http_client_cleanup(client);
|
esp_http_client_cleanup(client);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void http_auth_digest(void)
|
static void http_auth_digest(void)
|
||||||
{
|
{
|
||||||
|
@ -433,7 +470,6 @@ static void http_perform_as_stream_reader(void)
|
||||||
}
|
}
|
||||||
esp_http_client_config_t config = {
|
esp_http_client_config_t config = {
|
||||||
.url = "http://httpbin.org/get",
|
.url = "http://httpbin.org/get",
|
||||||
.event_handler = _http_event_handler,
|
|
||||||
};
|
};
|
||||||
esp_http_client_handle_t client = esp_http_client_init(&config);
|
esp_http_client_handle_t client = esp_http_client_init(&config);
|
||||||
esp_err_t err;
|
esp_err_t err;
|
||||||
|
@ -511,13 +547,78 @@ static void https_with_invalid_url(void)
|
||||||
esp_http_client_cleanup(client);
|
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)
|
static void http_test_task(void *pvParameters)
|
||||||
{
|
{
|
||||||
http_rest_with_url();
|
http_rest_with_url();
|
||||||
http_rest_with_hostname_path();
|
http_rest_with_hostname_path();
|
||||||
|
#if CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH
|
||||||
http_auth_basic();
|
http_auth_basic();
|
||||||
http_auth_basic_redirect();
|
http_auth_basic_redirect();
|
||||||
|
#endif
|
||||||
http_auth_digest();
|
http_auth_digest();
|
||||||
http_relative_redirect();
|
http_relative_redirect();
|
||||||
http_absolute_redirect();
|
http_absolute_redirect();
|
||||||
|
@ -528,6 +629,7 @@ static void http_test_task(void *pvParameters)
|
||||||
http_perform_as_stream_reader();
|
http_perform_as_stream_reader();
|
||||||
https_async();
|
https_async();
|
||||||
https_with_invalid_url();
|
https_with_invalid_url();
|
||||||
|
http_native_request();
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Finish http example");
|
ESP_LOGI(TAG, "Finish http example");
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
|
|
Loading…
Reference in a new issue