Skip to content

Commit 7e9a7b2

Browse files
committed
Add HTTP QUERY method (RFC 10008)
Recognize QUERY in the request-line parser, expose HTTP_QUERY, and accept it on AsyncCallbackJsonWebHandler so safe, idempotent queries can carry a JSON body. Platform http_method mapping is gated until ESP-IDF/Arduino define HTTP_QUERY.
1 parent d009eff commit 7e9a7b2

6 files changed

Lines changed: 33 additions & 4 deletions

File tree

docs/requests.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,30 @@
66

77
```cpp
88
request->version(); // uint8_t: 0 = HTTP/1.0, 1 = HTTP/1.1
9-
request->method(); // enum: HTTP_GET, HTTP_POST, HTTP_DELETE, HTTP_PUT, HTTP_PATCH, HTTP_HEAD, HTTP_OPTIONS
9+
request->method(); // enum: HTTP_GET, HTTP_POST, HTTP_DELETE, HTTP_PUT, HTTP_PATCH, HTTP_HEAD, HTTP_OPTIONS, HTTP_QUERY, …
1010
request->url(); // String: URL of the request (not including host, port or GET parameters)
1111
request->host(); // String: The requested host (can be used for virtual hosting)
1212
request->contentType(); // String: ContentType of the request (not available in Handler::canHandle)
1313
request->contentLength(); // size_t: ContentLength of the request (not available in Handler::canHandle)
1414
request->multipart(); // bool: True if the request has content type "multipart"
1515
```
1616

17+
`HTTP_QUERY` is [RFC 10008](https://www.rfc-editor.org/rfc/rfc10008.html): a safe, idempotent method that carries the query in the request body (same body path as POST/PUT/PATCH whenever `Content-Length` or chunked transfer is present). `AsyncCallbackJsonWebHandler` accepts QUERY with `Content-Type: application/json`. Unknown methods still abort the connection.
18+
19+
Register it like any other verb:
20+
21+
```cpp
22+
server.on("/search", HTTP_QUERY, [](AsyncWebServerRequest *request) {
23+
request->send(200, "text/plain", "ok");
24+
});
25+
26+
auto *json = new AsyncCallbackJsonWebHandler("/search", [](AsyncWebServerRequest *request, JsonVariant &json) {
27+
request->send(200, "application/json", "{\"ok\":true}");
28+
});
29+
json->setMethod(HTTP_QUERY);
30+
server.addHandler(json);
31+
```
32+
1733
### Headers
1834
1935
```cpp

examples/arduino/WebDAVMethods/WebDAVMethods.ino

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ using namespace asyncsrv;
3131
// curl -s -X MKCOL http://192.168.4.1/
3232
// curl -s -X MOVE http://192.168.4.1/
3333
// curl -s -X COPY http://192.168.4.1/
34+
// curl -s -X QUERY -H 'Content-Type: application/json' -d '{"q":1}' http://192.168.4.1/
3435
//
3536
// In all cases, the request will be accepted with text/plain response 200 like
3637
// "Got method PROPFIND on URL /"

src/AsyncJson.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,17 +113,18 @@ size_t AsyncMessagePackResponse::_fillBuffer(uint8_t *data, size_t len) {
113113

114114
// Body handler supporting both content types: JSON and MessagePack
115115
constexpr static WebRequestMethodComposite JsonHandlerMethods =
116-
AsyncWebRequestMethod::HTTP_GET | AsyncWebRequestMethod::HTTP_POST | AsyncWebRequestMethod::HTTP_PUT | AsyncWebRequestMethod::HTTP_PATCH;
116+
AsyncWebRequestMethod::HTTP_GET | AsyncWebRequestMethod::HTTP_POST | AsyncWebRequestMethod::HTTP_PUT | AsyncWebRequestMethod::HTTP_PATCH
117+
| AsyncWebRequestMethod::HTTP_QUERY;
117118

118119
#if ARDUINOJSON_VERSION_MAJOR == 6
119120
AsyncCallbackJsonWebHandler::AsyncCallbackJsonWebHandler(AsyncURIMatcher uri, ArJsonRequestHandlerFunction onRequest, size_t maxJsonBufferSize)
120121
: _uri(std::move(uri)),
121-
_method(AsyncWebRequestMethod::HTTP_GET | AsyncWebRequestMethod::HTTP_POST | AsyncWebRequestMethod::HTTP_PUT | AsyncWebRequestMethod::HTTP_PATCH),
122+
_method(JsonHandlerMethods),
122123
_onRequest(onRequest), maxJsonBufferSize(maxJsonBufferSize), _maxContentLength(16384) {}
123124
#else
124125
AsyncCallbackJsonWebHandler::AsyncCallbackJsonWebHandler(AsyncURIMatcher uri, ArJsonRequestHandlerFunction onRequest)
125126
: _uri(std::move(uri)),
126-
_method(AsyncWebRequestMethod::HTTP_GET | AsyncWebRequestMethod::HTTP_POST | AsyncWebRequestMethod::HTTP_PUT | AsyncWebRequestMethod::HTTP_PATCH),
127+
_method(JsonHandlerMethods),
127128
_onRequest(onRequest), _maxContentLength(16384) {}
128129
#endif
129130

src/ESPAsyncWebServer.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ enum AsyncWebRequestMethodType : uint32_t {
151151
HTTP_LINK = 1u << 22,
152152
HTTP_UNLINK = 1u << 23,
153153

154+
/* RFC 10008 */
155+
HTTP_QUERY = 1u << 24,
156+
154157
/* icecast */
155158
// HTTP_SOURCE
156159

@@ -227,6 +230,9 @@ class WebRequestMethodComposite {
227230
: MAP_EXTERNAL_TERNARY(HTTP_PURGE)
228231
: MAP_EXTERNAL_TERNARY(HTTP_LINK)
229232
: MAP_EXTERNAL_TERNARY(HTTP_UNLINK)
233+
#if defined(HTTP_QUERY)
234+
: MAP_EXTERNAL_TERNARY(HTTP_QUERY)
235+
#endif
230236
#if defined(HTTP_ANY)
231237
: (t == HTTP_ANY) ? static_cast<uint32_t>(WebRequestMethod::HTTP_INVALID) - 1
232238
#endif

src/WebRequest.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,6 +1544,8 @@ WebRequestMethod stringToMethod(const String &m) {
15441544
return AsyncWebRequestMethod::HTTP_UNBIND;
15451545
} else if (m == T_ACL) {
15461546
return AsyncWebRequestMethod::HTTP_ACL;
1547+
} else if (m == T_QUERY) {
1548+
return AsyncWebRequestMethod::HTTP_QUERY;
15471549
} else {
15481550
return AsyncWebRequestMethod::HTTP_INVALID;
15491551
}
@@ -1579,6 +1581,8 @@ const char *methodToString(WebRequestMethod method) {
15791581
/* RFC-2068, section 19.6.1.2 */
15801582
case AsyncWebRequestMethod::HTTP_LINK: return T_LINK;
15811583
case AsyncWebRequestMethod::HTTP_UNLINK: return T_UNLINK;
1584+
/* RFC 10008 */
1585+
case AsyncWebRequestMethod::HTTP_QUERY: return T_QUERY;
15821586
// Unsupported
15831587
default: return T_UNKNOWN;
15841588
}

src/literals.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ static constexpr const char T_ACL[] = "ACL";
137137
static constexpr const char T_PURGE[] = "PURGE";
138138
static constexpr const char T_LINK[] = "LINK";
139139
static constexpr const char T_UNLINK[] = "UNLINK";
140+
static constexpr const char T_QUERY[] = "QUERY";
140141

141142
// Req content types
142143
static constexpr const char T_RCT_HTTP[] = "RCT_HTTP";

0 commit comments

Comments
 (0)