Add query_has_key for efficient hasArg without string allocation

hasArg only needs to know if a key exists, not its value.
query_has_key uses a 1-byte buffer and checks the return code
from httpd_query_key_value — no url_decode, no std::string.
This commit is contained in:
J. Nick Koston
2026-02-11 18:23:38 -06:00
parent 592d5ec24c
commit e42cc2e394
3 changed files with 22 additions and 1 deletions

View File

@@ -88,6 +88,17 @@ optional<std::string> query_key_value(const char *query_url, size_t query_len, c
return {val.get()};
}
bool query_has_key(const char *query_url, size_t query_len, const char *key) {
if (query_url == nullptr || query_len == 0) {
return false;
}
// Minimal buffer — we only care if the key exists, not the value
char buf[1];
// httpd_query_key_value returns ESP_OK if key found (even if buffer too small for value),
// ESP_ERR_NOT_FOUND if key absent
return httpd_query_key_value(query_url, key, buf, sizeof(buf)) != ESP_ERR_NOT_FOUND;
}
// Helper function for case-insensitive string region comparison
bool str_ncmp_ci(const char *s1, const char *s2, size_t n) {
for (size_t i = 0; i < n; i++) {

View File

@@ -18,6 +18,7 @@ optional<std::string> query_key_value(const char *query_url, size_t query_len, c
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());
}
bool query_has_key(const char *query_url, size_t query_len, const char *key);
// Helper function for case-insensitive character comparison
inline bool char_equals_ci(char a, char b) { return ::tolower(a) == ::tolower(b); }

View File

@@ -424,7 +424,16 @@ optional<std::string> AsyncWebServerRequest::find_query_value_(const char *name)
return {};
}
bool AsyncWebServerRequest::hasArg(const char *name) { return this->find_query_value_(name).has_value(); }
bool AsyncWebServerRequest::hasArg(const char *name) {
if (query_has_key(this->post_query_.c_str(), this->post_query_.size(), name)) {
return true;
}
auto url_query = request_get_url_query(*this);
if (url_query.has_value()) {
return query_has_key(url_query.value().c_str(), url_query.value().size(), name);
}
return false;
}
std::string AsyncWebServerRequest::arg(const char *name) {
auto val = this->find_query_value_(name);