diff --git a/examples/WebDAVMethods/WebDAVMethods.ino b/examples/WebDAVMethods/WebDAVMethods.ino new file mode 100644 index 00000000..86b8b633 --- /dev/null +++ b/examples/WebDAVMethods/WebDAVMethods.ino @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright 2016-2026 Hristo Gochkov, Mathieu Carbou, Emil Muratov, Mitch Bradley + +// +// - Test for additional WebDAV request methods +// + +#include +#if defined(ESP32) || defined(LIBRETINY) +#include +#include +#elif defined(ESP8266) +#include +#include +#elif defined(TARGET_RP2040) || defined(TARGET_RP2350) || defined(PICO_RP2040) || defined(PICO_RP2350) +#include +#include +#endif + +#include + +using namespace asyncsrv; + +// Tests: +// +// Send requests with various methods +// curl -s -X PROPFIND http://192.168.4.1/ +// curl -s -X LOCK http://192.168.4.1/ +// curl -s -X UNLOCK http://192.168.4.1/ +// curl -s -X PROPPATCH http://192.168.4.1/ +// curl -s -X MKCOL http://192.168.4.1/ +// curl -s -X MOVE http://192.168.4.1/ +// curl -s -X COPY http://192.168.4.1/ +// +// In all cases, the request will be accepted with text/plain response 200 like +// "Got method PROPFIND on URL /" + +static AsyncWebServer server(80); + +void setup() { + Serial.begin(115200); + +#if ASYNCWEBSERVER_WIFI_SUPPORTED + WiFi.mode(WIFI_AP); + WiFi.softAP("esp-captive"); +#endif + + server.onNotFound([](AsyncWebServerRequest *request) { + String resp("Got method "); + resp += request->methodToString(); + resp += " on URL "; + resp += request->url(); + resp += "\r\n"; + + Serial.print(resp); + + request->send(200, "text/plain", resp.c_str()); + }); + + server.begin(); +} + +void loop() { + delay(100); +} diff --git a/platformio.ini b/platformio.ini index 6c294c25..d3d6a573 100644 --- a/platformio.ini +++ b/platformio.ini @@ -39,6 +39,7 @@ src_dir = examples/PerfTests ; src_dir = examples/URIMatcherTest ; src_dir = examples/WebSocket ; src_dir = examples/WebSocketEasy +; src_dir = examples/WebDAVMethods [env] framework = arduino diff --git a/src/ESPAsyncWebServer.h b/src/ESPAsyncWebServer.h index 80ceb303..68939e56 100644 --- a/src/ESPAsyncWebServer.h +++ b/src/ESPAsyncWebServer.h @@ -85,14 +85,22 @@ typedef enum http_method WebRequestMethod; #else #ifndef WEBSERVER_H typedef enum { - HTTP_GET = 0b00000001, - HTTP_POST = 0b00000010, - HTTP_DELETE = 0b00000100, - HTTP_PUT = 0b00001000, - HTTP_PATCH = 0b00010000, - HTTP_HEAD = 0b00100000, - HTTP_OPTIONS = 0b01000000, - HTTP_ANY = 0b01111111, + HTTP_GET = 0b0000000000000001, + HTTP_POST = 0b0000000000000010, + HTTP_DELETE = 0b0000000000000100, + HTTP_PUT = 0b0000000000001000, + HTTP_PATCH = 0b0000000000010000, + HTTP_HEAD = 0b0000000000100000, + HTTP_OPTIONS = 0b0000000001000000, + HTTP_PROPFIND = 0b0000000010000000, + HTTP_LOCK = 0b0000000100000000, + HTTP_UNLOCK = 0b0000001000000000, + HTTP_PROPPATCH = 0b0000010000000000, + HTTP_MKCOL = 0b0000100000000000, + HTTP_MOVE = 0b0001000000000000, + HTTP_COPY = 0b0010000000000000, + HTTP_RESERVED = 0b0100000000000000, + HTTP_ANY = 0b0111111111111111, } WebRequestMethod; #endif #endif @@ -114,7 +122,7 @@ class FileOpenMode { #define RESPONSE_TRY_AGAIN 0xFFFFFFFF #define RESPONSE_STREAM_BUFFER_SIZE 1460 -typedef uint8_t WebRequestMethodComposite; +typedef uint16_t WebRequestMethodComposite; typedef std::function ArDisconnectHandler; /* diff --git a/src/WebRequest.cpp b/src/WebRequest.cpp index 261dde12..8918f8b7 100644 --- a/src/WebRequest.cpp +++ b/src/WebRequest.cpp @@ -309,6 +309,20 @@ bool AsyncWebServerRequest::_parseReqHead() { _method = HTTP_HEAD; } else if (m == T_OPTIONS) { _method = HTTP_OPTIONS; + } else if (m == T_PROPFIND) { + _method = HTTP_PROPFIND; + } else if (m == T_LOCK) { + _method = HTTP_LOCK; + } else if (m == T_UNLOCK) { + _method = HTTP_UNLOCK; + } else if (m == T_PROPPATCH) { + _method = HTTP_PROPPATCH; + } else if (m == T_MKCOL) { + _method = HTTP_MKCOL; + } else if (m == T_MOVE) { + _method = HTTP_MOVE; + } else if (m == T_COPY) { + _method = HTTP_COPY; } else { return false; } @@ -1154,6 +1168,27 @@ const char *AsyncWebServerRequest::methodToString() const { if (_method & HTTP_OPTIONS) { return T_OPTIONS; } + if (_method & HTTP_PROPFIND) { + return T_PROPFIND; + } + if (_method & HTTP_LOCK) { + return T_LOCK; + } + if (_method & HTTP_UNLOCK) { + return T_UNLOCK; + } + if (_method & HTTP_PROPPATCH) { + return T_PROPPATCH; + } + if (_method & HTTP_MKCOL) { + return T_MKCOL; + } + if (_method & HTTP_MOVE) { + return T_MOVE; + } + if (_method & HTTP_COPY) { + return T_COPY; + } return T_UNKNOWN; } diff --git a/src/literals.h b/src/literals.h index 52ecb6c2..40c80a74 100644 --- a/src/literals.h +++ b/src/literals.h @@ -111,6 +111,13 @@ static constexpr const char T_DELETE[] = "DELETE"; static constexpr const char T_PATCH[] = "PATCH"; static constexpr const char T_HEAD[] = "HEAD"; static constexpr const char T_OPTIONS[] = "OPTIONS"; +static constexpr const char T_PROPFIND[] = "PROPFIND"; +static constexpr const char T_LOCK[] = "LOCK"; +static constexpr const char T_UNLOCK[] = "UNLOCK"; +static constexpr const char T_PROPPATCH[] = "PROPPATCH"; +static constexpr const char T_MKCOL[] = "MKCOL"; +static constexpr const char T_MOVE[] = "MOVE"; +static constexpr const char T_COPY[] = "COPY"; static constexpr const char T_UNKNOWN[] = "UNKNOWN"; // Req content types @@ -183,6 +190,7 @@ DECLARE_STR(T_HTTP_CODE_203, "Non-Authoritative Information"); DECLARE_STR(T_HTTP_CODE_204, "No Content"); DECLARE_STR(T_HTTP_CODE_205, "Reset Content"); DECLARE_STR(T_HTTP_CODE_206, "Partial Content"); +DECLARE_STR(T_HTTP_CODE_207, "Multi Status"); DECLARE_STR(T_HTTP_CODE_300, "Multiple Choices"); DECLARE_STR(T_HTTP_CODE_301, "Moved Permanently"); DECLARE_STR(T_HTTP_CODE_302, "Found");