SensESP 3.0.1
Universal Signal K sensor toolkit ESP32
Loading...
Searching...
No Matches
http_server.h
Go to the documentation of this file.
1#ifndef SENSESP_NET_HTTP_SERVER_H_
2#define SENSESP_NET_HTTP_SERVER_H_
3
4#include "sensesp.h"
5
6#include <ESPmDNS.h>
7#include <esp_http_server.h>
8#include <functional>
9#include <list>
10#include <memory>
11
12#include "WiFi.h"
15#include "sensesp_base_app.h"
16
17#ifndef HTTP_SERVER_STACK_SIZE
18#define HTTP_SERVER_STACK_SIZE 8192
19#endif
20
21namespace sensesp {
22
23#ifndef HTTP_DEFAULT_PORT
24#define HTTP_DEFAULT_PORT 80
25#endif
26
27#include <ctype.h>
28#include <stdlib.h>
29
30void urldecode2(char* dst, const char* src);
31String get_content_type(httpd_req_t* req);
32esp_err_t call_request_dispatcher(httpd_req_t* req);
33
34class HTTPServer;
35
41 public:
42 HTTPRequestHandler(uint32_t method_mask, String match_uri,
43 std::function<esp_err_t(httpd_req_t*)> handler_func)
44 : method_mask_(method_mask),
45 match_uri_(match_uri),
46 handler_func_(handler_func) {}
47
48 const uint32_t method_mask_;
49 const String match_uri_;
50
51 esp_err_t call(httpd_req_t* req) { return this->handler_func_(req); }
52
53 protected:
54 const std::function<esp_err_t(httpd_req_t*)> handler_func_;
55};
56
62 public:
64 const String& config_path = "/system/httpserver")
65 : FileSystemSaveable(config_path), config_(HTTPD_DEFAULT_CONFIG()) {
66 config_.server_port = port;
68 config_.max_uri_handlers = 20;
69 config_.uri_match_fn = httpd_uri_match_wildcard;
70 String auth_realm_ = "Login required for " + SensESPBaseApp::get_hostname();
71 load();
72 if (auth_required_) {
73 authenticator_ = std::unique_ptr<HTTPDigestAuthenticator>(
75 }
76 event_loop()->onDelay(0, [this]() {
77 esp_err_t error = httpd_start(&server_, &config_);
78 if (error != ESP_OK) {
79 ESP_LOGE(__FILENAME__, "Error starting HTTP server: %s",
80 esp_err_to_name(error));
81 } else {
82 ESP_LOGI(__FILENAME__, "HTTP server started");
83 }
84
85 // register the request dispatcher for all methods and all URIs
86 httpd_uri_t uri = {
87 .uri = "/*",
88 .method = HTTP_GET,
89 .handler = call_request_dispatcher,
90 .user_ctx = this,
91 .is_websocket = false,
92 };
93 httpd_register_uri_handler(server_, &uri);
94 uri.method = HTTP_HEAD;
95 httpd_register_uri_handler(server_, &uri);
96 uri.method = HTTP_POST;
97 httpd_register_uri_handler(server_, &uri);
98 uri.method = HTTP_PUT;
99 httpd_register_uri_handler(server_, &uri);
100 uri.method = HTTP_DELETE;
101 httpd_register_uri_handler(server_, &uri);
102
103 // announce the server over mDNS
104 MDNS.addService("http", "tcp", 80);
105 });
106 };
107
108 void stop() { httpd_stop(server_); }
109
110 void set_auth_credentials(const String& username, const String& password,
111 bool auth_required = true) {
112 username_ = username;
113 password_ = password;
114 auth_required_ = auth_required;
115 }
116
117 void set_captive_portal(bool captive_portal) {
118 captive_portal_ = captive_portal;
119 }
120
121 virtual bool to_json(JsonObject& config) override {
122 config["auth_required"] = auth_required_;
123 config["username"] = username_;
124 config["password"] = password_;
125
126 return true;
127 }
128
129 virtual bool from_json(const JsonObject& config) override {
130 if (config["auth_required"].is<bool>()) {
131 auth_required_ = config["auth_required"];
132 }
133 if (config["username"].is<String>()) {
134 username_ = config["username"].as<String>();
135 }
136 if (config["password"].is<String>()) {
137 password_ = config["password"].as<String>();
138 }
139 return true;
140 }
141
142 void add_handler(std::shared_ptr<HTTPRequestHandler>& handler) {
143 handlers_.push_back(handler);
144 }
145
146 protected:
147 bool captive_portal_ = false;
148 httpd_handle_t server_ = nullptr;
149 httpd_config_t config_;
150 String username_;
151 String password_;
152 bool auth_required_ = false;
153 std::unique_ptr<HTTPAuthenticator> authenticator_;
154
156 std::function<esp_err_t(httpd_req_t*)> handler,
157 httpd_req_t* req);
158
166 esp_err_t dispatch_request(httpd_req_t* req);
167
175 bool handle_captive_portal(httpd_req_t* req);
176
177 std::list<std::shared_ptr<HTTPRequestHandler>> handlers_;
178
179 friend esp_err_t call_request_dispatcher(httpd_req_t* req);
180};
181
182inline const String ConfigSchema(const HTTPServer& obj) {
183 return "null";
184}
185
186inline bool ConfigRequiresRestart(const HTTPServer& obj) { return true; }
187
188} // namespace sensesp
189
190#endif // SENSESP_NET_HTTP_SERVER_H_
virtual bool load() override
Load and populate the object from a persistent storage.
Definition saveable.cpp:8
HTTP Authenticator base class.
HTTP Digest Authenticator class.
HTTP request handler storage class.
Definition http_server.h:40
const uint32_t method_mask_
Definition http_server.h:48
HTTPRequestHandler(uint32_t method_mask, String match_uri, std::function< esp_err_t(httpd_req_t *)> handler_func)
Definition http_server.h:42
const std::function< esp_err_t(httpd_req_t *)> handler_func_
Definition http_server.h:54
esp_err_t call(httpd_req_t *req)
Definition http_server.h:51
HTTP server class wrapping the esp-idf http server.
Definition http_server.h:61
esp_err_t dispatch_request(httpd_req_t *req)
Dispatcher method that captures all requests and forwards them to the appropriate handlers.
virtual bool to_json(JsonObject &config) override
void set_captive_portal(bool captive_portal)
std::list< std::shared_ptr< HTTPRequestHandler > > handlers_
httpd_handle_t server_
void set_auth_credentials(const String &username, const String &password, bool auth_required=true)
bool authenticate_request(HTTPAuthenticator *auth, std::function< esp_err_t(httpd_req_t *)> handler, httpd_req_t *req)
friend esp_err_t call_request_dispatcher(httpd_req_t *req)
httpd_config_t config_
virtual bool from_json(const JsonObject &config) override
void add_handler(std::shared_ptr< HTTPRequestHandler > &handler)
HTTPServer(int port=HTTP_DEFAULT_PORT, const String &config_path="/system/httpserver")
Definition http_server.h:63
std::unique_ptr< HTTPAuthenticator > authenticator_
bool handle_captive_portal(httpd_req_t *req)
Check if the request is for the captive portal and handle it if it.
static String get_hostname()
Get the current hostname.
#define HTTP_DEFAULT_PORT
Definition http_server.h:24
#define HTTP_SERVER_STACK_SIZE
Definition http_server.h:18
const String ConfigSchema(const SmartSwitchController &obj)
std::shared_ptr< reactesp::EventLoop > event_loop()
Definition sensesp.cpp:9
esp_err_t call_request_dispatcher(httpd_req_t *req)
void urldecode2(char *dst, const char *src)
bool ConfigRequiresRestart(const HTTPServer &obj)
String get_content_type(httpd_req_t *req)