mirror of
https://github.com/esphome/esphome.git
synced 2025-10-06 20:03:46 +01:00
Merge branch 'idf_query' into integration
This commit is contained in:
@@ -190,8 +190,8 @@ esp_err_t AsyncWebServer::request_handler_(AsyncWebServerRequest *request) const
|
||||
|
||||
AsyncWebServerRequest::~AsyncWebServerRequest() {
|
||||
delete this->rsp_;
|
||||
for (const auto &pair : this->params_) {
|
||||
delete pair.second; // NOLINT(cppcoreguidelines-owning-memory)
|
||||
for (auto *param : this->params_) {
|
||||
delete param; // NOLINT(cppcoreguidelines-owning-memory)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,10 +231,23 @@ void AsyncWebServerRequest::redirect(const std::string &url) {
|
||||
}
|
||||
|
||||
void AsyncWebServerRequest::init_response_(AsyncWebServerResponse *rsp, int code, const char *content_type) {
|
||||
httpd_resp_set_status(*this, code == 200 ? HTTPD_200
|
||||
: code == 404 ? HTTPD_404
|
||||
: code == 409 ? HTTPD_409
|
||||
: to_string(code).c_str());
|
||||
// Set status code - use constants for common codes to avoid string allocation
|
||||
const char *status;
|
||||
switch (code) {
|
||||
case 200:
|
||||
status = HTTPD_200;
|
||||
break;
|
||||
case 404:
|
||||
status = HTTPD_404;
|
||||
break;
|
||||
case 409:
|
||||
status = HTTPD_409;
|
||||
break;
|
||||
default:
|
||||
status = to_string(code).c_str();
|
||||
break;
|
||||
}
|
||||
httpd_resp_set_status(*this, status);
|
||||
|
||||
if (content_type && *content_type) {
|
||||
httpd_resp_set_type(*this, content_type);
|
||||
@@ -291,11 +304,14 @@ void AsyncWebServerRequest::requestAuthentication(const char *realm) const {
|
||||
#endif
|
||||
|
||||
AsyncWebParameter *AsyncWebServerRequest::getParam(const std::string &name) {
|
||||
auto find = this->params_.find(name);
|
||||
if (find != this->params_.end()) {
|
||||
return find->second;
|
||||
// Check cache first - only successful lookups are cached
|
||||
for (auto *param : this->params_) {
|
||||
if (param->name() == name) {
|
||||
return param;
|
||||
}
|
||||
}
|
||||
|
||||
// Look up value from query strings
|
||||
optional<std::string> val = query_key_value(this->post_query_, name);
|
||||
if (!val.has_value()) {
|
||||
auto url_query = request_get_url_query(*this);
|
||||
@@ -304,11 +320,14 @@ AsyncWebParameter *AsyncWebServerRequest::getParam(const std::string &name) {
|
||||
}
|
||||
}
|
||||
|
||||
AsyncWebParameter *param = nullptr;
|
||||
if (val.has_value()) {
|
||||
param = new AsyncWebParameter(val.value()); // NOLINT(cppcoreguidelines-owning-memory)
|
||||
// Don't cache misses to prevent memory exhaustion from malicious requests
|
||||
// with thousands of non-existent parameter lookups
|
||||
if (!val.has_value()) {
|
||||
return nullptr;
|
||||
}
|
||||
this->params_.insert({name, param});
|
||||
|
||||
auto *param = new AsyncWebParameter(name, val.value()); // NOLINT(cppcoreguidelines-owning-memory)
|
||||
this->params_.push_back(param);
|
||||
return param;
|
||||
}
|
||||
|
||||
|
@@ -24,10 +24,12 @@ namespace web_server_idf {
|
||||
|
||||
class AsyncWebParameter {
|
||||
public:
|
||||
AsyncWebParameter(std::string value) : value_(std::move(value)) {}
|
||||
AsyncWebParameter(std::string name, std::string value) : name_(std::move(name)), value_(std::move(value)) {}
|
||||
const std::string &name() const { return this->name_; }
|
||||
const std::string &value() const { return this->value_; }
|
||||
|
||||
protected:
|
||||
std::string name_;
|
||||
std::string value_;
|
||||
};
|
||||
|
||||
@@ -168,7 +170,10 @@ class AsyncWebServerRequest {
|
||||
protected:
|
||||
httpd_req_t *req_;
|
||||
AsyncWebServerResponse *rsp_{};
|
||||
std::map<std::string, AsyncWebParameter *> params_;
|
||||
// Use vector instead of map/unordered_map: most requests have 0-3 params, so linear search
|
||||
// is faster than tree/hash overhead. AsyncWebParameter stores both name and value to avoid
|
||||
// duplicate storage. Only successful lookups are cached to prevent memory exhaustion attacks.
|
||||
std::vector<AsyncWebParameter *> params_;
|
||||
std::string post_query_;
|
||||
AsyncWebServerRequest(httpd_req_t *req) : req_(req) {}
|
||||
AsyncWebServerRequest(httpd_req_t *req, std::string post_query) : req_(req), post_query_(std::move(post_query)) {}
|
||||
|
Reference in New Issue
Block a user