[web_server_idf] Add const char* overloads for getParam/hasParam to avoid temporary string allocations

This commit is contained in:
J. Nick Koston
2026-02-03 15:30:40 +01:00
parent 21bd0ff6aa
commit f021df399e
4 changed files with 20 additions and 15 deletions

View File

@@ -73,18 +73,15 @@ optional<std::string> request_get_url_query(httpd_req_t *req) {
return {str};
}
optional<std::string> query_key_value(const std::string &query_url, const std::string &key) {
if (query_url.empty()) {
optional<std::string> query_key_value(const char *query_url, size_t query_len, const char *key) {
if (query_url == nullptr || query_len == 0) {
return {};
}
auto val = std::unique_ptr<char[]>(new char[query_url.size()]);
if (!val) {
ESP_LOGE(TAG, "Not enough memory to the query key value");
return {};
}
// Use stack buffer for typical query strings, heap fallback for large ones
SmallBufferWithHeapFallback<256, char> val(query_len);
if (httpd_query_key_value(query_url.c_str(), key.c_str(), val.get(), query_url.size()) != ESP_OK) {
if (httpd_query_key_value(query_url, key, val.get(), query_len) != ESP_OK) {
return {};
}

View File

@@ -15,7 +15,10 @@ size_t url_decode(char *str);
bool request_has_header(httpd_req_t *req, const char *name);
optional<std::string> request_get_header(httpd_req_t *req, const char *name);
optional<std::string> request_get_url_query(httpd_req_t *req);
optional<std::string> query_key_value(const std::string &query_url, const std::string &key);
optional<std::string> query_key_value(const char *query_url, size_t query_len, const char *key);
inline optional<std::string> query_key_value(const std::string &query_url, const std::string &key) {
return query_key_value(query_url.c_str(), query_url.size(), key.c_str());
}
// Helper function for case-insensitive character comparison
inline bool char_equals_ci(char a, char b) { return ::tolower(a) == ::tolower(b); }

View File

@@ -366,7 +366,7 @@ void AsyncWebServerRequest::requestAuthentication(const char *realm) const {
}
#endif
AsyncWebParameter *AsyncWebServerRequest::getParam(const std::string &name) {
AsyncWebParameter *AsyncWebServerRequest::getParam(const char *name) {
// Check cache first - only successful lookups are cached
for (auto *param : this->params_) {
if (param->name() == name) {
@@ -375,11 +375,11 @@ AsyncWebParameter *AsyncWebServerRequest::getParam(const std::string &name) {
}
// Look up value from query strings
optional<std::string> val = query_key_value(this->post_query_, name);
optional<std::string> val = query_key_value(this->post_query_.c_str(), this->post_query_.size(), name);
if (!val.has_value()) {
auto url_query = request_get_url_query(*this);
if (url_query.has_value()) {
val = query_key_value(url_query.value(), name);
val = query_key_value(url_query.value().c_str(), url_query.value().size(), name);
}
}

View File

@@ -162,19 +162,24 @@ class AsyncWebServerRequest {
}
// NOLINTNEXTLINE(readability-identifier-naming)
bool hasParam(const std::string &name) { return this->getParam(name) != nullptr; }
bool hasParam(const char *name) { return this->getParam(name) != nullptr; }
// NOLINTNEXTLINE(readability-identifier-naming)
AsyncWebParameter *getParam(const std::string &name);
bool hasParam(const std::string &name) { return this->getParam(name.c_str()) != nullptr; }
// NOLINTNEXTLINE(readability-identifier-naming)
AsyncWebParameter *getParam(const char *name);
// NOLINTNEXTLINE(readability-identifier-naming)
AsyncWebParameter *getParam(const std::string &name) { return this->getParam(name.c_str()); }
// NOLINTNEXTLINE(readability-identifier-naming)
bool hasArg(const char *name) { return this->hasParam(name); }
std::string arg(const std::string &name) {
std::string arg(const char *name) {
auto *param = this->getParam(name);
if (param) {
return param->value();
}
return {};
}
std::string arg(const std::string &name) { return this->arg(name.c_str()); }
operator httpd_req_t *() const { return this->req_; }
optional<std::string> get_header(const char *name) const;