接受两个数字之间的 Uri
accepting Uri between 2 numbers
我正在通过 Visual Studio 代码开发 ESP-idf。目前我正在开发 Web 服务器实现,我想接受以下 url:
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;
我收到以下错误消息:
error: 'httpd_ssl_config_t' {aka 'struct httpd_ssl_config'} has no member named '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());
}
编辑 2:
我尝试了以下方法:
在 header 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(因此它是该结构的成员)。如果我在 header 中设置 .uri_match_fn = httpd_uri_match_wildcard \ 它确实有效,但我不想更改默认设置功能。我可以添加另一个实现 uri 通配符的函数,但我认为问题出在其他地方。
有人可能知道为什么会这样?
ISP IDF HTTP 服务器支持 custom URI matchers, where you can create your own logic for matching the incoming request URIs or use basic wildcard expressions。我没有时间深入研究用于生成示例代码的 API 文档,但它看起来相当简单。
经过搜索,我找到了一个说明它如何使用的示例:
您必须将 URI 匹配器设置为通配符匹配。
config.uri_match_fn = httpd_uri_match_wildcard;
static esp_err_t on_command_handler(httpd_req_t *req)
{
// req->uri is character array with request uri
// find the number after /on/ and validate
// and call httpd_resp_send_404(req)
return ESP_OK;
}
static const httpd_uri_t postCommandOn = {
.uri = "/command/on/*",
.method = HTTP_POST,
.handler = on_command_handler
};
httpd_register_uri_handler(server_handle, &postCommandOn);
我正在通过 Visual Studio 代码开发 ESP-idf。目前我正在开发 Web 服务器实现,我想接受以下 url:
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;
我收到以下错误消息:
error: 'httpd_ssl_config_t' {aka 'struct httpd_ssl_config'} has no member named '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());
}
编辑 2:
我尝试了以下方法: 在 header 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(因此它是该结构的成员)。如果我在 header 中设置 .uri_match_fn = httpd_uri_match_wildcard \ 它确实有效,但我不想更改默认设置功能。我可以添加另一个实现 uri 通配符的函数,但我认为问题出在其他地方。
有人可能知道为什么会这样?
ISP IDF HTTP 服务器支持 custom URI matchers, where you can create your own logic for matching the incoming request URIs or use basic wildcard expressions。我没有时间深入研究用于生成示例代码的 API 文档,但它看起来相当简单。
经过搜索,我找到了一个说明它如何使用的示例:
您必须将 URI 匹配器设置为通配符匹配。
config.uri_match_fn = httpd_uri_match_wildcard;
static esp_err_t on_command_handler(httpd_req_t *req)
{
// req->uri is character array with request uri
// find the number after /on/ and validate
// and call httpd_resp_send_404(req)
return ESP_OK;
}
static const httpd_uri_t postCommandOn = {
.uri = "/command/on/*",
.method = HTTP_POST,
.handler = on_command_handler
};
httpd_register_uri_handler(server_handle, &postCommandOn);