【发布时间】:2021-12-13 12:42:38
【问题描述】:
我正在通过 Visual Studio Code 开发 ESP-idf。目前我正在开发一个网络服务器实现,我想接受以下网址:
IPADDRESS/command/on/5(1 到 32 之间的数字)
最简单(但不是很有效)的解决方案是,像这样初始化每个 uri
static const httpd_uri_t postCommandOn = {
.uri = "/command/on/1",
.method = HTTP_POST,
.handler = on_command_handler
};
static const httpd_uri_t postCommandOn = {
.uri = "/command/on/2",
.method = HTTP_POST,
.handler = on_command_handler
};
等等。
但是不应该有更简单的方法吗? 提前致谢!
问候
编辑: 好吧,我不知道它是怎么发生的,但我的整个项目现在已经消失了。
我尝试重做我的步骤,但遇到了一个我很确定上次不存在的新问题。
当我尝试添加这一行时:
conf.uri_match_fn = httpd_uri_match_wildcard;
我收到以下错误消息:
错误:“httpd_ssl_config_t”{又名“struct httpd_ssl_config”}没有名为“uri_to_match”的成员
conf.uri_to_match = httpd_uri_match_wildcard;
我不知道为什么会突然出现,但我真的不知道我与上次插入此行时所做的不同。
我的 main.c 文件现在看起来像这样:
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#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 "esp_netif.h"
#include "esp_eth.h"
#include "protocol_examples_common.h"
#include <esp_https_server.h>
/* A simple example that demonstrates how to create GET and POST
* handlers and start an HTTPS server.
*/
static const char *TAG = "example";
/* An HTTP GET handler */
static esp_err_t root_get_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "text/html");
httpd_resp_send(req, "<h1>Hello Secure World!</h1>", HTTPD_RESP_USE_STRLEN);
return ESP_OK;
}
static esp_err_t status_get_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "text/html");
httpd_resp_send(req, "<h1>Hello Secure World!</h1>", HTTPD_RESP_USE_STRLEN);
return ESP_OK;
}
static esp_err_t command_on_post_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "text/html");
httpd_resp_send(req, "<h1>Hello Secure World!</h1>", HTTPD_RESP_USE_STRLEN);
return ESP_OK;
}
static esp_err_t command_off_post_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "text/html");
httpd_resp_send(req, "<h1>Hello Secure World!</h1>", HTTPD_RESP_USE_STRLEN);
return ESP_OK;
}
static const httpd_uri_t getStatus = {
.uri = "/status",
.method = HTTP_GET,
.handler = status_get_handler
};
static const httpd_uri_t postCommandOn = {
.uri = "/command/on/*",
.method = HTTP_POST,
.handler = command_on_post_handler
};
static const httpd_uri_t postCommandOff = {
.uri = "/command/off/*",
.method = HTTP_POST,
.handler = command_off_post_handler
};
static const httpd_uri_t root = {
.uri = "/",
.method = HTTP_GET,
.handler = root_get_handler
};
static httpd_handle_t start_webserver(void)
{
httpd_handle_t server = NULL;
// Start the httpd server
ESP_LOGI(TAG, "Starting server");
httpd_ssl_config_t conf = HTTPD_SSL_CONFIG_DEFAULT();
extern const unsigned char cacert_pem_start[] asm("_binary_cacert_pem_start");
extern const unsigned char cacert_pem_end[] asm("_binary_cacert_pem_end");
conf.cacert_pem = cacert_pem_start;
conf.cacert_len = cacert_pem_end - cacert_pem_start;
extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start");
extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end");
conf.prvtkey_pem = prvtkey_pem_start;
conf.prvtkey_len = prvtkey_pem_end - prvtkey_pem_start;
//////////////////////////////////////////////////////////
//////////this line causes the problem///////////////////
conf.uri_match_fn = httpd_uri_match_wildcard;
esp_err_t ret = httpd_ssl_start(&server, &conf);
if (ESP_OK != ret) {
ESP_LOGI(TAG, "Error starting server!");
return NULL;
}
// Set URI handlers
ESP_LOGI(TAG, "Registering URI handlers");
httpd_register_uri_handler(server, &root);
httpd_register_uri_handler(server, &getStatus);
httpd_register_uri_handler(server, &postCommandOff);
httpd_register_uri_handler(server, &postCommandOn);
return server;
}
static void stop_webserver(httpd_handle_t server)
{
// Stop the httpd server
httpd_ssl_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) {
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) {
*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());
/* Register event handlers to start server when Wi-Fi or Ethernet is connected,
* and stop server when disconnection happens.
*/
#ifdef CONFIG_EXAMPLE_CONNECT_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 // CONFIG_EXAMPLE_CONNECT_WIFI
#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 // CONFIG_EXAMPLE_CONNECT_ETHERNET
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
* Read "Establishing Wi-Fi or Ethernet Connection" section in
* examples/protocols/README.md for more information about this function.
*/
ESP_ERROR_CHECK(example_connect());
}
EDIT2:
我尝试了以下方法: 在头文件 esp_https_server.h conf 中定义如下 =
.httpd = { \
.task_priority = tskIDLE_PRIORITY+5, \
.stack_size = 10240, \
.core_id = tskNO_AFFINITY, \
.server_port = 0, \
.ctrl_port = 32768, \
.max_open_sockets = 4, \
.max_uri_handlers = 8, \
.max_resp_headers = 8, \
.backlog_conn = 5, \
.lru_purge_enable = true, \
.recv_wait_timeout = 5, \
.send_wait_timeout = 5, \
.global_user_ctx = NULL, \
.global_user_ctx_free_fn = NULL, \
.global_transport_ctx = NULL, \
.global_transport_ctx_free_fn = NULL, \
.open_fn = NULL, \
.close_fn = NULL, \
.uri_match_fn = NULL \ //this is the part which is "no member"
}, \
.cacert_pem = NULL, \
.cacert_len = 0, \
.client_verify_cert_pem = NULL, \
.client_verify_cert_len = 0, \
.prvtkey_pem = NULL, \
.prvtkey_len = 0, \
.transport_mode = HTTPD_SSL_TRANSPORT_SECURE, \
.port_secure = 443, \
.port_insecure = 80, \
}
您可以清楚地看到,.uri_match_fn 设置为 NULL(因此它是该结构的成员)。如果我在标题中设置 .uri_match_fn = httpd_uri_match_wildcard \ 它确实有效,但我不想更改默认设置功能。我可以添加另一个实现 uri 通配符的函数,但我认为问题出在其他地方。
有人可能有一个想法,为什么会这样?
【问题讨论】:
-
如果 URL 路由器不支持正则表达式或通配符 (
[2-8]),您必须在处理程序中实现它并路由/command/on,如果 URL 非法则返回404 -
好吧,我认为不支持正则表达式或通配符。你的意思是在处理程序中实现它,我应该解析传入的非法 uri 和路由,以防它采用我想要的格式?
-
如果 uri 匹配是前缀匹配(他们没有在文档中说明,请尝试 uri="/command/on/"),在处理程序中检查 @987654328 之后的数字@ 有效,如果没有设置响应
404并退出 -
我想我开始理解你的方法了。但是,如果我在“/on/”之后添加一个数字(例如 /on/6),我将无法访问我的处理程序,因为我得到响应“找不到 url”。