ESP32-http server笔记
基于ESP-IDF4.1
#include <esp_wifi.h> #include <esp_event.h> #include <esp_log.h> #include <esp_system.h> #include <nvs_flash.h> #include <sys/param.h> #include "nvs_flash.h" #include "esp_netif.h" #include "esp_eth.h" #include "protocol_examples_common.h" #include <esp_http_server.h> /* * 演示服务端创建get和post处理服务 */ static const char *TAG = "example"; /* HTTP GET 处理程序 */ static esp_err_t hello_get_handler(httpd_req_t *req) { char* buf; size_t buf_len; //获取消息头值得长度并且分配内存,而外1个字节存储null终止符 buf_len = httpd_req_get_hdr_value_len(req, "Host") + 1; if (buf_len > 1) { buf = malloc(buf_len); /* 将null结尾的字符串值复制到缓冲区 */ if (httpd_req_get_hdr_value_str(req, "Host", buf, buf_len) == ESP_OK) { ESP_LOGI(TAG, "Found header => Host: %s", buf); } free(buf); } buf_len = httpd_req_get_hdr_value_len(req, "Test-Header-2") + 1; if (buf_len > 1) { buf = malloc(buf_len); if (httpd_req_get_hdr_value_str(req, "Test-Header-2", buf, buf_len) == ESP_OK) { ESP_LOGI(TAG, "Found header => Test-Header-2: %s", buf); } free(buf); } buf_len = httpd_req_get_hdr_value_len(req, "Test-Header-1") + 1; if (buf_len > 1) { buf = malloc(buf_len); if (httpd_req_get_hdr_value_str(req, "Test-Header-1", buf, buf_len) == ESP_OK) { ESP_LOGI(TAG, "Found header => Test-Header-1: %s", buf); } free(buf); } // 读取URL查询字符串长度并分配内存空间 buf_len = httpd_req_get_url_query_len(req) + 1; if (buf_len > 1) { buf = malloc(buf_len); if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) { ESP_LOGI(TAG, "Found URL query => %s", buf); char param[32]; // 从查询字符串获取键值 if (httpd_query_key_value(buf, "query1", param, sizeof(param)) == ESP_OK) { ESP_LOGI(TAG, "Found URL query parameter => query1=%s", param); } if (httpd_query_key_value(buf, "query3", param, sizeof(param)) == ESP_OK) { ESP_LOGI(TAG, "Found URL query parameter => query3=%s", param); } if (httpd_query_key_value(buf, "query2", param, sizeof(param)) == ESP_OK) { ESP_LOGI(TAG, "Found URL query parameter => query2=%s", param); } } free(buf); } /* 设置自定义消息头 */ httpd_resp_set_hdr(req, "Custom-Header-1", "Custom-Value-1"); httpd_resp_set_hdr(req, "Custom-Header-2", "Custom-Value-2"); //用户上下文通过字符串响应自定义消息头和消息体 const char* resp_str = (const char*) req->user_ctx; httpd_resp_send(req, resp_str, strlen(resp_str)); //检查http请求消息头是否可以被读取 if (httpd_req_get_hdr_value_len(req, "Host") == 0) { ESP_LOGI(TAG, "Request headers lost"); } return ESP_OK; } static const httpd_uri_t hello = { .uri = "/hello", .method = HTTP_GET, .handler = hello_get_handler, .user_ctx = "Hello World!" }; /* HTTP POST处理 */ static esp_err_t echo_post_handler(httpd_req_t *req) { char buf[100]; int ret, remaining = req->content_len; while (remaining > 0) { /* Read the data for the request */ if ((ret = httpd_req_recv(req, buf, MIN(remaining, sizeof(buf)))) <= 0) { if (ret == HTTPD_SOCK_ERR_TIMEOUT) { /* Retry receiving if timeout occurred */ continue; } return ESP_FAIL; } /* Send back the same data */ httpd_resp_send_chunk(req, buf, ret); remaining -= ret; /* Log data received */ ESP_LOGI(TAG, "=========== RECEIVED DATA =========="); ESP_LOGI(TAG, "%.*s", ret, buf); ESP_LOGI(TAG, "===================================="); } // End response httpd_resp_send_chunk(req, NULL, 0); return ESP_OK; } static const httpd_uri_t echo = { .uri = "/echo", .method = HTTP_POST, .handler = echo_post_handler, .user_ctx = NULL }; /* * 自定义错误处理 */ esp_err_t http_404_error_handler(httpd_req_t *req, httpd_err_code_t err) { if (strcmp("/hello", req->uri) == 0) { httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "/hello URI is not available"); /* Return ESP_OK to keep underlying socket open */ return ESP_OK; } else if (strcmp("/echo", req->uri) == 0) { httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "/echo URI is not available"); /* Return ESP_FAIL to close underlying socket */ return ESP_FAIL; } /* For any other URI send 404 and close socket */ httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "Some 404 error message"); return ESP_FAIL; } /* * HTTP POST处理程序 */ static esp_err_t ctrl_put_handler(httpd_req_t *req) { char buf; int ret; if ((ret = httpd_req_recv(req, &buf, 1)) <= 0) { if (ret == HTTPD_SOCK_ERR_TIMEOUT) { httpd_resp_send_408(req); } return ESP_FAIL; } if (buf == '0') { /* URI handlers can be unregistered using the uri string */ ESP_LOGI(TAG, "Unregistering /hello and /echo URIs"); httpd_unregister_uri(req->handle, "/hello"); httpd_unregister_uri(req->handle, "/echo"); /* Register the custom error handler */ httpd_register_err_handler(req->handle, HTTPD_404_NOT_FOUND, http_404_error_handler); } else { ESP_LOGI(TAG, "Registering /hello and /echo URIs"); httpd_register_uri_handler(req->handle, &hello); httpd_register_uri_handler(req->handle, &echo); /* Unregister custom error handler */ httpd_register_err_handler(req->handle, HTTPD_404_NOT_FOUND, NULL); } /* Respond with empty body */ httpd_resp_send(req, NULL, 0); return ESP_OK; } static const httpd_uri_t ctrl = { .uri = "/ctrl", .method = HTTP_PUT, .handler = ctrl_put_handler, .user_ctx = NULL }; //启动web服务 static httpd_handle_t start_webserver(void) { httpd_handle_t server = NULL; httpd_config_t config = HTTPD_DEFAULT_CONFIG(); // 启动httpd服务 ESP_LOGI(TAG, "Starting server on port: '%d'", config.server_port); if (httpd_start(&server, &config) == ESP_OK) { // 设置URI处理程序 ESP_LOGI(TAG, "Registering URI handlers"); httpd_register_uri_handler(server, &hello); httpd_register_uri_handler(server, &echo); httpd_register_uri_handler(server, &ctrl); return server; } ESP_LOGI(TAG, "Error starting server!"); return NULL; } //停止web服务 static void stop_webserver(httpd_handle_t server) { // 停止httpd服务 httpd_stop(server); } //断网处理程序 static void disconnect_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { httpd_handle_t* server = (httpd_handle_t*) arg; if (*server) { ESP_LOGI(TAG, "Stopping webserver"); stop_webserver(*server); *server = NULL; } } //联网处理程序 static void connect_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { httpd_handle_t* server = (httpd_handle_t*) arg; if (*server == NULL) { ESP_LOGI(TAG, "Starting webserver"); *server = start_webserver(); } } //入口 void app_main(void) { static httpd_handle_t server = NULL; ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(example_connect()); /* * 注册事件处理服务,当断开网络时停止服务,当连接网络时重启 */ #ifdef CONFIG_EXAMPLE_CONNECT_WIFI //连接wifi ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &connect_handler, &server)); ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &disconnect_handler, &server)); #endif #ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET //连接以太网 ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &connect_handler, &server)); ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, &disconnect_handler, &server)); #endif //启动服务 server = start_webserver(); }
需要包含的文件:https://gitee.com/EspressifSystems/esp-idf/tree/master/examples/common_components/protocol_examples_common
原文:https://gitee.com/EspressifSystems/esp-idf