25 const std::shared_ptr<ConfigItemBase>& item) {
26 JsonObject obj = doc.to<JsonObject>();
29 serializeJson(doc, str);
31 obj[
"path"] = item->get_config_path();
32 obj[
"title"] = item->get_title();
33 obj[
"description"] = item->get_description();
34 obj[
"requires_restart"] = item->requires_restart();
35 obj[
"schema"] = serialized(item->get_config_schema());
39 JsonObject config = obj[
"config"].to<JsonObject>();
40 bool result = item->to_json(config);
42 serializeJson(obj, str);
44 if (doc.overflowed()) {
45 ESP_LOGE(
"ConfigHandler",
"JSON document overflowed");
53 ESP_LOGI(
"ConfigHandler",
"GET request to URL %.*s", uri_path_len(req->uri),
55 String url = String(req->uri);
57 if (url.indexOf(
'?') != -1) {
58 query = url.substring(url.indexOf(
'?') + 1);
61 bool cards_only =
false;
64 if (query ==
"cards") {
66 }
else if (query !=
"") {
67 httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST,
"Invalid query");
71 JsonDocument json_doc;
72 JsonArray arr = json_doc.to<JsonArray>();
76 for (
auto it = config_items->begin(); it != config_items->end(); ++it) {
78 ((*it)->get_config_schema() ==
"null" ||
79 (*it)->get_config_schema() ==
"{}" || (*it)->get_title() ==
"")) {
82 const String& path = (*it)->get_config_path();
86 auto obj = arr.add(path);
90 serializeJson(json_doc, response);
91 httpd_resp_set_type(req,
"application/json");
92 httpd_resp_sendstr(req, response.c_str());
103 auto handler = std::make_shared<HTTPRequestHandler>(
104 1 << HTTP_GET,
"/api/config/*", [](httpd_req_t* req) {
105 ESP_LOGD(
"ConfigHandler",
"GET request to URL %.*s",
106 uri_path_len(req->uri), req->uri);
107 String url_tail = String(req->uri).substring(11);
110 if (url_tail.indexOf(
'?') != -1) {
111 path = url_tail.substring(0, url_tail.indexOf(
'?'));
112 query = url_tail.substring(url_tail.indexOf(
'?') + 1);
116 char path_cstr[path.length() + 1];
118 url_tail = String(path_cstr);
120 if (path.length() == 0) {
127 if (config_item ==
nullptr) {
128 httpd_resp_send_err(req, HTTPD_404_NOT_FOUND,
129 "No ConfigItem found with that path");
138 serializeJson(doc, response);
139 httpd_resp_set_type(req,
"application/json");
140 httpd_resp_sendstr(req, response.c_str());
143 server->add_handler(handler);
147 auto handler = std::make_shared<HTTPRequestHandler>(
148 1 << HTTP_PUT,
"/api/config/*",
149 [](httpd_req_t* req) {
150 ESP_LOGI(__FILENAME__,
"PUT request to URL %.*s",
151 uri_path_len(req->uri), req->uri);
153 httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST,
154 "application/json content type expected");
159 String url_tail = String(req->uri).substring(11);
160 if (url_tail.length() == 0) {
161 httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST,
162 "No configuration path specified");
167 char url_tail_cstr[url_tail.length() + 1];
169 url_tail = String(url_tail_cstr);
173 if (config_item ==
nullptr) {
174 httpd_resp_send_err(req, HTTPD_404_NOT_FOUND,
175 "No Configurable found with that path");
180 constexpr size_t kMaxConfigPayloadSize = 4096;
181 size_t payload_len = req->content_len;
182 if (payload_len > kMaxConfigPayloadSize) {
183 httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST,
"Payload too large");
186 std::unique_ptr<char[]> payload(
new char[payload_len + 1]);
187 int ret = httpd_req_recv(req, payload.get(), payload_len);
189 httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR,
190 "Error receiving payload");
193 payload[payload_len] =
'\0';
195 ESP_LOGV(
"ConfigHandler",
"Received payload: %s", payload.get());
199 DeserializationError error = deserializeJson(doc, payload.get());
201 ESP_LOGE(
"ConfigHandler",
"Error parsing JSON payload: %s",
203 httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST,
204 "Error parsing JSON payload");
209 bool result = config_item->from_json(doc.as<JsonObject>());
211 ESP_LOGE(
"ConfigHandler",
"Error applying JSON payload");
212 httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST,
213 "Invalid JSON payload");
217 response =
"{\"status\":\"ok\"}";
219 httpd_resp_set_type(req,
"application/json");
220 httpd_resp_sendstr(req, response.c_str());
224 server->add_handler(handler);