1. 代码
#include "esp_http_server.h"
#include "esp_log.h"
#include "web_server.h"
// 辅助宏,用于计算两个数中的较小值
#define MIN(a, b) ((a) < (b) ? (a) : (b))
static const char *TAG = "wifi web_server";
const char login_page[] = {"\
<!DOCTYPE html>\
<html>\
<head>\
<meta charset='UTF-8'>\
<title>Sensor Configuration</title>\
</head>\
<body>\
<form method='POST' action='login.html'>\
<br>\
<P align=center style='color:#0066ff'><b>Sensor</b></P>\
<br><br>\
<P align=center>登录密码:    <input name=PASSWORD type=password size=18 maxlength=15></P>\
<br>\
<P align=center><input type=submit value='进入'></P>\
</form>\
</body>\
</html>\
"};
const char str_password_ok[] = "Password validated successfully";
const char str_password_ng[] = "Invalid password";
const char str_password_lost[] = "Missing PASSWORD field";
// HTTP服务器配置
esp_err_t http_get_handler(httpd_req_t *req)
{
// const char* resp_str = "<html><body><h1>Hello ESP8266!</h1></body></html>";
const char* resp_str = login_page;
ESP_LOGI(TAG, "send login html");
httpd_resp_send(req, resp_str, strlen(resp_str));
return ESP_OK;
}
// 预期的密码
static const char *expected_password = "88888";
// 用于存储从请求体中读取的数据(注意:这里使用了固定大小)
#define REQUEST_BODY_MAX_SIZE 1024
static char request_body[REQUEST_BODY_MAX_SIZE] = {0};
static size_t request_body_len = 0;
// 辅助函数:从请求中读取数据(使用固定大小缓冲区)
static esp_err_t read_request_body(httpd_req_t *req) {
//char buffer[128]; // 临时缓冲区,小于总缓冲区大小
int len;
// 循环读取请求体数据,直到没有更多数据可读或缓冲区满
len = httpd_req_recv(req, request_body, REQUEST_BODY_MAX_SIZE - 1);
if (len == HTTPD_SOCK_ERR_TIMEOUT) {
// 超时错误处理
ESP_LOGE("http_server", "Read timeout");
return ESP_ERR_TIMEOUT;
} else if (len < 0) {
// 读取错误处理
ESP_LOGE("http_server", "Error reading request body");
return ESP_FAIL;
}
// 确保字符串以 null 结尾
request_body[len] = '\0';
request_body_len = len; // 更新请求体长度
return ESP_OK;
}
esp_err_t http_post_handler(httpd_req_t *req) {
// 重置请求体缓冲区
memset(request_body, 0, REQUEST_BODY_MAX_SIZE);
request_body_len = 0;
// 读取整个请求体
if (read_request_body(req) != ESP_OK) {
// 读取请求体时发生错误
httpd_resp_send_500(req);
return ESP_FAIL;
}
// 假设请求体是 URL 编码的,并且包含 PASSWORD=...
char *password_start = strstr(request_body, "PASSWORD=");
if (password_start != NULL) {
password_start += strlen("PASSWORD=");
char *password_end = strchr(password_start, '&'); // 查找下一个字段的开始或字符串末尾
if (password_end == NULL) {
password_end = password_start + strlen(password_start); // 如果没有 '&',则指向末尾
}
// 计算密码长度(注意:这里要防止越界)
size_t password_len = MIN(password_end - password_start, strlen(expected_password));
// 比较密码
if (strncmp(password_start, expected_password, password_len) == 0 &&
(password_len == strlen(expected_password) || *(password_end - 1) == '&')) {
httpd_resp_send(req, str_password_ok,strlen(str_password_ok)); //HTTP_OK
} else {
httpd_resp_send(req, str_password_ng,strlen(str_password_ng)); //HTTP_UNAUTHORIZED,
}
} else {
httpd_resp_send(req, str_password_lost,strlen(str_password_lost)); //HTTP_BAD_REQUEST,
}
return ESP_OK;
}
httpd_handle_t start_webserver(void)
{
httpd_handle_t server = NULL;
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
// GET 请求处理
httpd_uri_t get_uri = {
.uri = "/",
.method = HTTP_GET,
.handler = http_get_handler,
.user_ctx = NULL
};
// POST 请求处理(注意:这里假设表单提交到 /login)
httpd_uri_t post_uri = {
.uri = "/login.html",
.method = HTTP_POST,
.handler = http_post_handler,
.user_ctx = NULL
};
// 启动HTTP服务器
if (httpd_start(&server, &config) == ESP_OK) {
ESP_LOGI(TAG, "Server started");
if (httpd_register_uri_handler(server, &get_uri) != ESP_OK) {
ESP_LOGE(TAG, "Failed to register GET URI handler");
}
if (httpd_register_uri_handler(server, &post_uri) != ESP_OK) {
ESP_LOGE(TAG, "Failed to register POST URI handler");
}
} else {
ESP_LOGE(TAG, "Failed to start server");
}
return server;
}
2 . 密码错误、正确的网页效果