Skip to content

HTTP库

HTTP server库

基础使用

用于从 ESP-IDF 应用程序中发起 HTTP/S 请求

c
esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *config);
  • 其次调用 esp_http_client_perform(),执行 esp_http_client 的所有操作,包括打开连接、交换数据、关闭连接(如需要),同时在当前任务完成前阻塞该任务。所有相关的事件(在 esp_http_client_config_t 中指定)将通过事件处理程序被调用。

esp_http_client_open -> esp_http_client_write -> esp_http_client_fetch_headers -> esp_http_client_read (and option) esp_http_client_close

c
esp_err_t esp_http_client_perform(esp_http_client_handle_t client);
  • 最后调用 esp_http_client_cleanup() 来关闭连接(如有),并释放所有分配给 HTTP 客户端实例的内存。此函数必须在操作完成后最后一个被调用。
c
char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0};
int https_status = 0;
int64_t gzip_len = 0;

memset(dstBuf, 0, 1024);

esp_http_client_config_t config = {
    .url = "https://devapi.qweather.com/v7/weather/now?location=101010100&key=7be28a7cc429438abf4f1d5feeb9c910",
    .event_handler = _http_event_handler, //事件处理回调函数
    .crt_bundle_attach = esp_crt_bundle_attach,
    .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_err_t err = esp_http_client_perform(client);
//获取信息
https_status = esp_http_client_get_status_code(client);
gzip_len = esp_http_client_get_content_length(client);

if (err == ESP_OK) {
    ESP_LOGI(TAG, "HTTPS Status = %d, content_length = %"PRIu64,
             https_status,
             gzip_len);
} else {
    ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err));
}
esp_http_client_cleanup(client);

设置post数据

c
esp_err_t esp_http_client_set_post_field(esp_http_client_handle_t client, const char *data, int len);
int esp_http_client_get_post_field(esp_http_client_handle_t client, char **data);

通过post方式请求的数据,传入发送数据的缓存地址与长度,必须在esp_http_client_perform之前调用

设置header

c
esp_err_t esp_http_client_set_header(esp_http_client_handle_t client, const char *key, const char *value);
esp_err_t esp_http_client_get_header(esp_http_client_handle_t client, const char *key, char **value);
esp_err_t esp_http_client_delete_header(esp_http_client_handle_t client, const char *key);

设置、获取、删除请求头,可新增、删除或根据应用发送的数据类型来自定义请求文件类型来修改请求头

esp_http_client_set_header(client, "HeaderKey", "HeaderValue");

请求方式

c
//请求方式枚举
typedef enum {
    HTTP_METHOD_GET = 0,    /*!< HTTP GET Method */
    HTTP_METHOD_POST,       /*!< HTTP POST Method */
    HTTP_METHOD_PUT,        /*!< HTTP PUT Method */
    HTTP_METHOD_PATCH,      /*!< HTTP PATCH Method */
    HTTP_METHOD_DELETE,     /*!< HTTP DELETE Method */
    HTTP_METHOD_HEAD,       /*!< HTTP HEAD Method */
    HTTP_METHOD_NOTIFY,     /*!< HTTP NOTIFY Method */
    HTTP_METHOD_SUBSCRIBE,  /*!< HTTP SUBSCRIBE Method */
    HTTP_METHOD_UNSUBSCRIBE,/*!< HTTP UNSUBSCRIBE Method */
    HTTP_METHOD_OPTIONS,    /*!< HTTP OPTIONS Method */
    HTTP_METHOD_COPY,       /*!< HTTP COPY Method */
    HTTP_METHOD_MOVE,       /*!< HTTP MOVE Method */
    HTTP_METHOD_LOCK,       /*!< HTTP LOCK Method */
    HTTP_METHOD_UNLOCK,     /*!< HTTP UNLOCK Method */
    HTTP_METHOD_PROPFIND,   /*!< HTTP PROPFIND Method */
    HTTP_METHOD_PROPPATCH,  /*!< HTTP PROPPATCH Method */
    HTTP_METHOD_MKCOL,      /*!< HTTP MKCOL Method */
    HTTP_METHOD_MAX,
} esp_http_client_method_t;

esp_http_client_set_method(client, HTTP_METHOD_GET);//GET请求

HTTP事件

c
/**
 * @brief HTTP configuration
 */
typedef struct {
    const char                  *url; //url请求接口必须配置               
    /*!< HTTP URL, the information on the URL is most important, it overrides 
    the other fields below, if any */
    const char                  *host; //服务器域名或ip地址              
    /*!< Domain or IP as string */
    int                             port; //端口 http默认80 https 默认443                
    /*!< Port to connect, default depend on esp_http_client_transport_t (80 or 443) */
    const char                  *username;  
    //用户名,认证使用        
    /*!< Using for Http authentication */
    const char                  *password;  //用户密码,认证使用        
    /*!< Using for Http authentication */
    esp_http_client_auth_type_t auth_type; //认证方式          
    /*!< Http authentication type, see `esp_http_client_auth_type_t` */
    const char                  *path;  //路径             
    /*!< HTTP Path, if not set, default is `/` */
    const char                  *query;  //请求参数            
    /*!< HTTP query */
    const char                  *cert_pem;    //证书       
    /*!< SSL server certification, PEM format as string, if the client requires 
    to verify server */
    const char                  *client_cert_pem;    
    /*!< SSL client certification, PEM format as string, if the server requires 
    to verify client */
    const char                  *client_key_pem;     
    /*!< SSL client key, PEM format as string, if the server requires to verify client */
    esp_http_client_method_t    method;  //请求方式 post get                 
    /*!< HTTP Method */
    int                         timeout_ms;  //请求超时             
    /*!< Network timeout in milliseconds */
    bool                        disable_auto_redirect;    
    /*!< Disable HTTP automatic redirects */
    int                         max_redirection_count;    
    /*!< Max number of redirections on receiving HTTP redirect status code, 
    using default value if zero*/
    int                         max_authorization_retries;    
    /*!< Max connection retries on receiving HTTP unauthorized status code, 
    using default value if zero. Disables authorization retry if -1*/
    http_event_handle_cb        event_handler;  //可注册回调           
    /*!< HTTP Event Handle */
    esp_http_client_transport_t transport_type;  // 传输方式 tcp ssl        
    /*!< HTTP transport type, see `esp_http_client_transport_t` */
    int                         buffer_size; //接收缓存大小             
    /*!< HTTP receive buffer size */
    int                         buffer_size_tx; //发送缓存大小          
    /*!< HTTP transmit buffer size */
    void                        *user_data;  //http用户数据             
    /*!< HTTP user_data context */
    bool                        is_async;  //同步模式               
    /*!< Set asynchronous mode, only supported with HTTPS for now */
    bool                        use_global_ca_store;       
    /*!< Use a global ca_store for all the connections in which this bool is set. */
    bool                        skip_cert_common_name_check; 
    //跳过证书   /*!< Skip any validation of server certificate CN field */
} esp_http_client_config_t;

这些事件可以使用事件处理回调函数进行处理, 这些回调函数的默认数据类型如下

HTTP_EVENT_ERROR : esp_http_client_handle_t

HTTP_EVENT_ON_CONNECTED : esp_http_client_handle_t

HTTP_EVENT_HEADERS_SENT : esp_http_client_handle_t

HTTP_EVENT_ON_HEADER : esp_http_client_handle_t

HTTP_EVENT_ON_DATA : esp_http_client_on_data_t

HTTP_EVENT_ON_FINISH : esp_http_client_handle_t

HTTP_EVENT_DISCONNECTED : esp_http_client_handle_t

HTTP_EVENT_REDIRECT : esp_http_client_redirect_event_data_t

c
//事件回调
static esp_err_t _http_event_handle(esp_http_client_event_t *evt)
{
    switch(evt->event_id) {
        case HTTP_EVENT_ERROR://错误事件
            ESP_LOGI(TAG, "HTTP_EVENT_ERROR");
            break;
        case HTTP_EVENT_ON_CONNECTED://连接成功事件
            ESP_LOGI(TAG, "HTTP_EVENT_ON_CONNECTED");
            break;
        case HTTP_EVENT_HEADER_SENT://发送头事件
            ESP_LOGI(TAG, "HTTP_EVENT_HEADER_SENT");
            break;
        case HTTP_EVENT_ON_HEADER://接收头事件
            ESP_LOGI(TAG, "HTTP_EVENT_ON_HEADER");
            printf("%.*s", evt->data_len, (char*)evt->data);
            break;
        case HTTP_EVENT_ON_DATA://接收数据事件
            ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
            if (!esp_http_client_is_chunked_response(evt->client)) {
                printf("%.*s", evt->data_len, (char*)evt->data);
            }
            break;
        case HTTP_EVENT_ON_FINISH://会话完成事件
            ESP_LOGI(TAG, "HTTP_EVENT_ON_FINISH");
            break;
        case HTTP_EVENT_DISCONNECTED://断开事件
            ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
            break;
    }
    return ESP_OK;
}
c
esp_http_client_config_t config = {
	.method = HTTP_METHOD_GET, //get请求
	.url = "https://www.baidu.com/", //请求url
	.event_handler = _http_event_handle,//注册时间回调
};

在init 的时候设置回调函数

配置结构体

c
/**
 * @brief HTTP configuration
 */
typedef struct {
    const char                  *url;                /*!< HTTP URL, the information on the URL
    is most important, it overrides the other fields below, if any 网址*/
    const char                  *host;               /*!< Domain or IP as string ip地址*/
    int                         port;                /*!< Port to connect, default depend on 
    esp_http_client_transport_t (80 or 443) 端口*/
    const char                  *username;           /*!< Using for Http authentication */
    const char                  *password;           /*!< Using for Http authentication */
    esp_http_client_auth_type_t auth_type;           /*!< Http authentication type, see 
    										`esp_http_client_auth_type_t` */
    const char                  *path;               /*!< HTTP Path, if not set, default is `/` */
    const char                  *query;              /*!< HTTP query 参数*/
    const char                  *cert_pem;           /*!< SSL server certification, PEM format
    as string, if the client requires to verify server */
    size_t                      cert_len;            /*!< Length of the buffer pointed to by
    cert_pem. May be 0 for null-terminated pem */
    const char                  *client_cert_pem;    /*!< SSL client certification, PEM format
    as string, if the server requires to verify client */
    size_t                      client_cert_len;     /*!< Length of the buffer pointed to by 
    client_cert_pem. May be 0 for null-terminated pem */
    const char                  *client_key_pem;     /*!< SSL client key, PEM format as 
    string, if the server requires to verify client */
    size_t                      client_key_len;      /*!< Length of the buffer pointed to by 
    client_key_pem. May be 0 for null-terminated pem */
    const char                  *client_key_password;      /*!< Client key decryption password
    string */
    size_t                      client_key_password_len;   /*!< String length of the password 
    pointed to by client_key_password */
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
    bool                        use_ecdsa_peripheral;       /*!< Use ECDSA peripheral to use
    private key. */
    uint8_t                     ecdsa_key_efuse_blk;        /*!< The efuse block where ECDSA key is stored. */
#endif
    const char                  *user_agent;         /*!< The User Agent string to send with
    HTTP requests */
    esp_http_client_method_t    method;                   /*!< HTTP Method */
    int                         timeout_ms;            /*!< Network timeout in milliseconds */
    bool                        disable_auto_redirect;    /*!< Disable HTTP automatic 
    redirects */
    int                         max_redirection_count;    /*!< Max number of redirections on 
    receiving HTTP redirect status code, using default value if zero*/
    int                         max_authorization_retries;    /*!< Max connection retries on 
    receiving HTTP unauthorized status code, using default value if zero. Disables 
    authorization retry if -1*/
    http_event_handle_cb        event_handler;             /*!< HTTP Event Handle事件处理函数*/
    esp_http_client_transport_t transport_type;           /*!< HTTP transport type, see 
    `esp_http_client_transport_t` */
    int                         buffer_size;              /*!< HTTP receive buffer size */
    int                         buffer_size_tx;           /*!< HTTP transmit buffer size */
    void                        *user_data;               /*!< HTTP user_data context 
    获取的信息*/
    bool                        is_async;                 /*!< Set asynchronous mode, only 
    supported with HTTPS for now */
    bool                        use_global_ca_store;      /*!< Use a global ca_store for all 
    the connections in which this bool is set. */
    bool                        skip_cert_common_name_check;    /*!< Skip any validation of 
    server certificate CN field */
    const char                  *common_name;             /*!< Pointer to the string 
    containing server certificate common name.
    If non-NULL, server certificate CN must match this name,
    If NULL, server certificate CN must match hostname. */
    esp_err_t (*crt_bundle_attach)(void *conf);      /*!< Function pointer to 
    esp_crt_bundle_attach. Enables the use of certification
    bundle for server verification, must be enabled in menuconfig */
    bool                        keep_alive_enable;   /*!< Enable keep-alive timeout */
    int                         keep_alive_idle;     /*!< Keep-alive idle time. Default is 5 
    (second) */
    int                         keep_alive_interval; /*!< Keep-alive interval time. Default is 
    5 (second) */
    int                         keep_alive_count;    /*!< Keep-alive packet retry send count. 
    Default is 3 counts */
    struct ifreq                *if_name;            /*!< The name of interface for data to go 
    through. Use the default interface without setting */
#if CONFIG_ESP_TLS_USE_SECURE_ELEMENT
    bool use_secure_element;                /*!< Enable this option to use secure element */
#endif
#if CONFIG_ESP_TLS_USE_DS_PERIPHERAL
    void *ds_data;                          /*!< Pointer for digital signature peripheral 
    context, see ESP-TLS Documentation for more details */
#endif
} esp_http_client_config_t;

HTTP server实现

这是个在的项目基础上面添

c
#include <esp_http_server.h>
http_config_t config = HTTPD_DEFAULT_CONFIG();
httpd_start
httpd_register_uri_handler
httpd_stop
c
//两个网页
const char mainpage[] = "<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n<meta charset=\"UTF-8\">\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n<title>你好</title>\r\n</head>\r\n<body>\r\n<div style=\"text-align: center;\">\r\n<h1>你好page1</h1>\r\n<hr size=3>\r\n<a href=\"index.html\">Back To Homepage</a>\r\n</div>\r\n</body>\r\n</html>\r\n";
const char mainpage2[] = "<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n<meta charset=\"UTF-8\">\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n<title>你好</title>\r\n</head>\r\n<body>\r\n<div style=\"text-align: center;\">\r\n<h1>你好page2</h1>\r\n<hr size=3>\r\n<a href=\"index.html\">Back To Homepage</a>\r\n</div>\r\n</body>\r\n</html>\r\n";

esp_err_t get_handler(httpd_req_t *req){
    httpd_resp_send(req, mainpage, HTTPD_RESP_USE_STRLEN);
    return ESP_OK;
}
esp_err_t post_handler(httpd_req_t *req){
    //获取数据
    char content[100];
    int totallen = req->content_len;
    size_t recv_size = MIN(req->content_len, sizeof(content));

    int len = 0;
    do{
        len = httpd_req_recv(req, content, recv_size);
        totallen-=len;
        printf("%s\n", content);
    }while(totallen > 0);
    //回复数据
    httpd_resp_send(req, mainpage2, strlen(mainpage2));
    return ESP_OK;
}


//网页设置
httpd_uri_t uri_get = {
    .uri = "geturl",
    .method = HTTP_GET, //处理的信号
    .handler = get_handler, //处理的函数
    .user_ctx = NULL
};

httpd_uri_t uri_post = {
    .uri = "posturl",
    .method = HTTP_POST,
    .handler = post_handler,
    .user_ctx = NULL
};
httpd_handle_t server_handler(void){
    //初始化
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    httpd_handle_t server = NULL;

    if(httpd_start(&server, &config)==ESP_OK){
        //注册两个网页
        httpd_register_uri_handler(server, &uri_get);
        httpd_register_uri_handler(server, &uri_post);
    }
    return server;
}

image-20240608232531346

HTTP client实现

域名转IP函数

c
#incldue "lwip/netdb.h"
getaddrinfo