From d56803f2d18b57c7a721e8140b0818470066267e Mon Sep 17 00:00:00 2001 From: Will Miles Date: Mon, 9 Mar 2026 15:57:44 +0000 Subject: [PATCH 1/4] Put HTTP_METHOD symbols in namespace Always formally define the WebRequestMethod type, and put the HTTP_METHOD symbols in a namespace that does not have to be included. This allows us to avoid collisions with other web server libraries that may define the same symbols globally. Also we remove the includes of such colliding symbols on RP-Pico targets. --- src/ESPAsyncWebServer.h | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/ESPAsyncWebServer.h b/src/ESPAsyncWebServer.h index de416f5f..0132b0b1 100644 --- a/src/ESPAsyncWebServer.h +++ b/src/ESPAsyncWebServer.h @@ -41,8 +41,6 @@ #include #elif defined(TARGET_RP2040) || defined(TARGET_RP2350) || defined(PICO_RP2040) || defined(PICO_RP2350) #include -#include -#include #else #error Platform not supported #endif @@ -80,11 +78,10 @@ class AsyncCallbackWebHandler; class AsyncResponseStream; class AsyncMiddlewareChain; -#if defined(TARGET_RP2040) || defined(TARGET_RP2350) || defined(PICO_RP2040) || defined(PICO_RP2350) -typedef enum http_method WebRequestMethod; -#else -#ifndef WEBSERVER_H -typedef enum { +// Namespace for web request method defines +namespace AsyncWebRequestMethod { +// The long name here is because we sometimes include this in the global namespace +enum AsyncWebRequestMethodType { HTTP_GET = 0b0000000000000001, HTTP_POST = 0b0000000000000010, HTTP_DELETE = 0b0000000000000100, @@ -101,8 +98,25 @@ typedef enum { HTTP_COPY = 0b0010000000000000, HTTP_RESERVED = 0b0100000000000000, HTTP_ANY = 0b0111111111111111, -} WebRequestMethod; -#endif +}; +}; // namespace AsyncWebRequestMethod + +typedef AsyncWebRequestMethod::AsyncWebRequestMethodType WebRequestMethod; +typedef uint16_t WebRequestMethodComposite; + +// Type-safe helper functions for composite methods +extern inline WebRequestMethodComposite operator|(WebRequestMethodComposite l, WebRequestMethod r) { + return l | static_cast(r); +}; +extern inline WebRequestMethodComposite operator|(WebRequestMethod l, WebRequestMethod r) { + return static_cast(l) | r; +}; + +#if !defined(ASYNCWEBSERVER_NO_GLOBAL_HTTP_METHODS) && !defined(WEBSERVER_H) +// Import the method enum values to the global namespace +// This will collide with some values on some platforms; +// for historical reasons they are assumed to be compatible. +using namespace AsyncWebRequestMethod; #endif #ifndef HAVE_FS_FILE_OPEN_MODE @@ -122,7 +136,6 @@ class FileOpenMode { #define RESPONSE_TRY_AGAIN 0xFFFFFFFF #define RESPONSE_STREAM_BUFFER_SIZE 1460 -typedef uint16_t WebRequestMethodComposite; typedef std::function ArDisconnectHandler; /* From a77aeafa371e1b1ebffefc5b6422fc5a739e8e19 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Mon, 9 Mar 2026 17:25:04 +0000 Subject: [PATCH 2/4] Fix ASYNCWEBSERVER_NO_GLOBAL_HTTP_METHODS Ensure we're always using our AsyncWebRequestMethod internally. --- src/AsyncJson.cpp | 1 + src/ESPAsyncWebServer.h | 6 +++--- src/Middleware.cpp | 2 +- src/WebHandlerImpl.h | 2 +- src/WebHandlers.cpp | 2 +- src/WebRequest.cpp | 3 +++ 6 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/AsyncJson.cpp b/src/AsyncJson.cpp index a85536c2..f10caab6 100644 --- a/src/AsyncJson.cpp +++ b/src/AsyncJson.cpp @@ -3,6 +3,7 @@ #include "AsyncJson.h" #include "AsyncWebServerLogging.h" +using namespace AsyncWebRequestMethod; #include diff --git a/src/ESPAsyncWebServer.h b/src/ESPAsyncWebServer.h index 0132b0b1..748f9541 100644 --- a/src/ESPAsyncWebServer.h +++ b/src/ESPAsyncWebServer.h @@ -385,10 +385,10 @@ class AsyncWebServerRequest { bool isExpectedRequestedConnType(RequestedConnectionType erct1, RequestedConnectionType erct2 = RCT_NOT_USED, RequestedConnectionType erct3 = RCT_NOT_USED) const; bool isWebSocketUpgrade() const { - return _method == HTTP_GET && isExpectedRequestedConnType(RCT_WS); + return _method == AsyncWebRequestMethod::HTTP_GET && isExpectedRequestedConnType(RCT_WS); } bool isSSE() const { - return _method == HTTP_GET && isExpectedRequestedConnType(RCT_EVENT); + return _method == AsyncWebRequestMethod::HTTP_GET && isExpectedRequestedConnType(RCT_EVENT); } bool isHTTP() const { return isExpectedRequestedConnType(RCT_DEFAULT, RCT_HTTP); @@ -1558,7 +1558,7 @@ class AsyncWebServer : public AsyncMiddlewareChain { bool removeHandler(AsyncWebHandler *handler); AsyncCallbackWebHandler &on(AsyncURIMatcher uri, ArRequestHandlerFunction onRequest) { - return on(std::move(uri), HTTP_ANY, onRequest); + return on(std::move(uri), AsyncWebRequestMethod::HTTP_ANY, onRequest); } AsyncCallbackWebHandler &on( AsyncURIMatcher uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload = nullptr, diff --git a/src/Middleware.cpp b/src/Middleware.cpp index 94a720ff..42c05af9 100644 --- a/src/Middleware.cpp +++ b/src/Middleware.cpp @@ -249,7 +249,7 @@ void AsyncCorsMiddleware::run(AsyncWebServerRequest *request, ArMiddlewareNext n // Origin header ? => CORS handling if (request->hasHeader(asyncsrv::T_CORS_O)) { // check if this is a preflight request => handle it and return - if (request->method() == HTTP_OPTIONS) { + if (request->method() == AsyncWebRequestMethod::HTTP_OPTIONS) { AsyncWebServerResponse *response = request->beginResponse(200); addCORSHeaders(request, response); request->send(response); diff --git a/src/WebHandlerImpl.h b/src/WebHandlerImpl.h index 5332e795..dac40c6e 100644 --- a/src/WebHandlerImpl.h +++ b/src/WebHandlerImpl.h @@ -62,7 +62,7 @@ class AsyncCallbackWebHandler : public AsyncWebHandler { bool _isRegex; public: - AsyncCallbackWebHandler() : _uri(), _method(HTTP_ANY), _onRequest(NULL), _onUpload(NULL), _onBody(NULL), _isRegex(false) {} + AsyncCallbackWebHandler() : _uri(), _method(AsyncWebRequestMethod::HTTP_ANY), _onRequest(NULL), _onUpload(NULL), _onBody(NULL), _isRegex(false) {} void setUri(AsyncURIMatcher uri); void setMethod(WebRequestMethodComposite method) { _method = method; diff --git a/src/WebHandlers.cpp b/src/WebHandlers.cpp index dd088322..7439f53f 100644 --- a/src/WebHandlers.cpp +++ b/src/WebHandlers.cpp @@ -103,7 +103,7 @@ AsyncStaticWebHandler &AsyncStaticWebHandler::setLastModified() { } bool AsyncStaticWebHandler::canHandle(AsyncWebServerRequest *request) const { - return request->isHTTP() && request->method() == HTTP_GET && request->url().startsWith(_uri) && _getFile(request); + return request->isHTTP() && request->method() == AsyncWebRequestMethod::HTTP_GET && request->url().startsWith(_uri) && _getFile(request); } bool AsyncStaticWebHandler::_getFile(AsyncWebServerRequest *request) const { diff --git a/src/WebRequest.cpp b/src/WebRequest.cpp index bf359822..59aef380 100644 --- a/src/WebRequest.cpp +++ b/src/WebRequest.cpp @@ -13,6 +13,9 @@ #include "./literals.h" +// Bring in HTTP namespace +using namespace AsyncWebRequestMethod; + static inline bool isParamChar(char c) { return ((c) && ((c) != '{') && ((c) != '[') && ((c) != '&') && ((c) != '=')); } From e5d7b2054978150e2f905b38fe71f549ccc4e2c5 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Mon, 9 Mar 2026 17:28:25 +0000 Subject: [PATCH 3/4] Remove webserver_h check --- src/ESPAsyncWebServer.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ESPAsyncWebServer.h b/src/ESPAsyncWebServer.h index 748f9541..81e6a07b 100644 --- a/src/ESPAsyncWebServer.h +++ b/src/ESPAsyncWebServer.h @@ -112,10 +112,8 @@ extern inline WebRequestMethodComposite operator|(WebRequestMethod l, WebRequest return static_cast(l) | r; }; -#if !defined(ASYNCWEBSERVER_NO_GLOBAL_HTTP_METHODS) && !defined(WEBSERVER_H) +#if !defined(ASYNCWEBSERVER_NO_GLOBAL_HTTP_METHODS) // Import the method enum values to the global namespace -// This will collide with some values on some platforms; -// for historical reasons they are assumed to be compatible. using namespace AsyncWebRequestMethod; #endif From e0c85cb3d41bd4701d976e8818ba4129292854cc Mon Sep 17 00:00:00 2001 From: Will Miles Date: Wed, 11 Mar 2026 20:17:31 -0400 Subject: [PATCH 4/4] Remove using AsyncWebRequestMethod Prefer fully qualitifed references instead. --- src/AsyncJson.cpp | 14 ++++---- src/ESPAsyncWebServer.h | 4 +-- src/WebRequest.cpp | 72 ++++++++++++++++++++--------------------- 3 files changed, 44 insertions(+), 46 deletions(-) diff --git a/src/AsyncJson.cpp b/src/AsyncJson.cpp index f10caab6..6147379d 100644 --- a/src/AsyncJson.cpp +++ b/src/AsyncJson.cpp @@ -3,7 +3,6 @@ #include "AsyncJson.h" #include "AsyncWebServerLogging.h" -using namespace AsyncWebRequestMethod; #include @@ -113,14 +112,15 @@ size_t AsyncMessagePackResponse::_fillBuffer(uint8_t *data, size_t len) { #endif // Body handler supporting both content types: JSON and MessagePack +constexpr static bool JsonHandlerMethods = + AsyncWebRequestMethod::HTTP_GET | AsyncWebRequestMethod::HTTP_POST | AsyncWebRequestMethod::HTTP_PUT | AsyncWebRequestMethod::HTTP_PATCH; #if ARDUINOJSON_VERSION_MAJOR == 6 AsyncCallbackJsonWebHandler::AsyncCallbackJsonWebHandler(AsyncURIMatcher uri, ArJsonRequestHandlerFunction onRequest, size_t maxJsonBufferSize) - : _uri(std::move(uri)), _method(HTTP_GET | HTTP_POST | HTTP_PUT | HTTP_PATCH), _onRequest(onRequest), maxJsonBufferSize(maxJsonBufferSize), - _maxContentLength(16384) {} + : _uri(std::move(uri)), _method(JsonHandlerTypes), _onRequest(onRequest), maxJsonBufferSize(maxJsonBufferSize), _maxContentLength(16384) {} #else AsyncCallbackJsonWebHandler::AsyncCallbackJsonWebHandler(AsyncURIMatcher uri, ArJsonRequestHandlerFunction onRequest) - : _uri(std::move(uri)), _method(HTTP_GET | HTTP_POST | HTTP_PUT | HTTP_PATCH), _onRequest(onRequest), _maxContentLength(16384) {} + : _uri(std::move(uri)), _method(JsonHandlerMethods), _onRequest(onRequest), _maxContentLength(16384) {} #endif bool AsyncCallbackJsonWebHandler::canHandle(AsyncWebServerRequest *request) const { @@ -133,17 +133,17 @@ bool AsyncCallbackJsonWebHandler::canHandle(AsyncWebServerRequest *request) cons } #if ASYNC_MSG_PACK_SUPPORT == 1 - return request->method() == HTTP_GET || request->contentType().equalsIgnoreCase(asyncsrv::T_application_json) + return request->method() == AsyncWebRequestMethod::HTTP_GET || request->contentType().equalsIgnoreCase(asyncsrv::T_application_json) || request->contentType().equalsIgnoreCase(asyncsrv::T_application_msgpack); #else - return request->method() == HTTP_GET || request->contentType().equalsIgnoreCase(asyncsrv::T_application_json); + return request->method() == AsyncWebRequestMethod::HTTP_GET || request->contentType().equalsIgnoreCase(asyncsrv::T_application_json); #endif } void AsyncCallbackJsonWebHandler::handleRequest(AsyncWebServerRequest *request) { if (_onRequest) { // GET request: - if (request->method() == HTTP_GET) { + if (request->method() == AsyncWebRequestMethod::HTTP_GET) { JsonVariant json; _onRequest(request, json); return; diff --git a/src/ESPAsyncWebServer.h b/src/ESPAsyncWebServer.h index 81e6a07b..76251d89 100644 --- a/src/ESPAsyncWebServer.h +++ b/src/ESPAsyncWebServer.h @@ -105,10 +105,10 @@ typedef AsyncWebRequestMethod::AsyncWebRequestMethodType WebRequestMethod; typedef uint16_t WebRequestMethodComposite; // Type-safe helper functions for composite methods -extern inline WebRequestMethodComposite operator|(WebRequestMethodComposite l, WebRequestMethod r) { +extern constexpr inline WebRequestMethodComposite operator|(WebRequestMethodComposite l, WebRequestMethod r) { return l | static_cast(r); }; -extern inline WebRequestMethodComposite operator|(WebRequestMethod l, WebRequestMethod r) { +extern constexpr inline WebRequestMethodComposite operator|(WebRequestMethod l, WebRequestMethod r) { return static_cast(l) | r; }; diff --git a/src/WebRequest.cpp b/src/WebRequest.cpp index 59aef380..3f38fc9d 100644 --- a/src/WebRequest.cpp +++ b/src/WebRequest.cpp @@ -13,9 +13,6 @@ #include "./literals.h" -// Bring in HTTP namespace -using namespace AsyncWebRequestMethod; - static inline bool isParamChar(char c) { return ((c) && ((c) != '{') && ((c) != '[') && ((c) != '&') && ((c) != '=')); } @@ -42,11 +39,12 @@ enum { }; AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer *s, AsyncClient *c) - : _client(c), _server(s), _handler(NULL), _response(NULL), _onDisconnectfn(NULL), _temp(), _parseState(PARSE_REQ_START), _version(0), _method(HTTP_ANY), - _url(), _host(), _contentType(), _boundary(), _authorization(), _reqconntype(RCT_HTTP), _authMethod(AsyncAuthType::AUTH_NONE), _isMultipart(false), - _isPlainPost(false), _expectingContinue(false), _contentLength(0), _parsedLength(0), _multiParseState(0), _boundaryPosition(0), _itemStartIndex(0), - _itemSize(0), _itemName(), _itemFilename(), _itemType(), _itemValue(), _itemBuffer(0), _itemBufferIndex(0), _itemIsFile(false), _chunkStartIndex(0), - _chunkOffset(0), _chunkSize(0), _chunkedParseState(CHUNK_NONE), _chunkedLastChar(0), _tempObject(NULL) { + : _client(c), _server(s), _handler(NULL), _response(NULL), _onDisconnectfn(NULL), _temp(), _parseState(PARSE_REQ_START), _version(0), + _method(AsyncWebRequestMethod::HTTP_ANY), _url(), _host(), _contentType(), _boundary(), _authorization(), _reqconntype(RCT_HTTP), + _authMethod(AsyncAuthType::AUTH_NONE), _isMultipart(false), _isPlainPost(false), _expectingContinue(false), _contentLength(0), _parsedLength(0), + _multiParseState(0), _boundaryPosition(0), _itemStartIndex(0), _itemSize(0), _itemName(), _itemFilename(), _itemType(), _itemValue(), _itemBuffer(0), + _itemBufferIndex(0), _itemIsFile(false), _chunkStartIndex(0), _chunkOffset(0), _chunkSize(0), _chunkedParseState(CHUNK_NONE), _chunkedLastChar(0), + _tempObject(NULL) { c->onError( [](void *r, AsyncClient *c, int8_t error) { (void)c; @@ -317,33 +315,33 @@ bool AsyncWebServerRequest::_parseReqHead() { _temp = _temp.substring(index + 1); if (m == T_GET) { - _method = HTTP_GET; + _method = AsyncWebRequestMethod::HTTP_GET; } else if (m == T_POST) { - _method = HTTP_POST; + _method = AsyncWebRequestMethod::HTTP_POST; } else if (m == T_DELETE) { - _method = HTTP_DELETE; + _method = AsyncWebRequestMethod::HTTP_DELETE; } else if (m == T_PUT) { - _method = HTTP_PUT; + _method = AsyncWebRequestMethod::HTTP_PUT; } else if (m == T_PATCH) { - _method = HTTP_PATCH; + _method = AsyncWebRequestMethod::HTTP_PATCH; } else if (m == T_HEAD) { - _method = HTTP_HEAD; + _method = AsyncWebRequestMethod::HTTP_HEAD; } else if (m == T_OPTIONS) { - _method = HTTP_OPTIONS; + _method = AsyncWebRequestMethod::HTTP_OPTIONS; } else if (m == T_PROPFIND) { - _method = HTTP_PROPFIND; + _method = AsyncWebRequestMethod::HTTP_PROPFIND; } else if (m == T_LOCK) { - _method = HTTP_LOCK; + _method = AsyncWebRequestMethod::HTTP_LOCK; } else if (m == T_UNLOCK) { - _method = HTTP_UNLOCK; + _method = AsyncWebRequestMethod::HTTP_UNLOCK; } else if (m == T_PROPPATCH) { - _method = HTTP_PROPPATCH; + _method = AsyncWebRequestMethod::HTTP_PROPPATCH; } else if (m == T_MKCOL) { - _method = HTTP_MKCOL; + _method = AsyncWebRequestMethod::HTTP_MKCOL; } else if (m == T_MOVE) { - _method = HTTP_MOVE; + _method = AsyncWebRequestMethod::HTTP_MOVE; } else if (m == T_COPY) { - _method = HTTP_COPY; + _method = AsyncWebRequestMethod::HTTP_COPY; } else { return false; } @@ -1314,49 +1312,49 @@ String AsyncWebServerRequest::urlDecode(const String &text) const { } const char *AsyncWebServerRequest::methodToString() const { - if (_method == HTTP_ANY) { + if (_method == AsyncWebRequestMethod::HTTP_ANY) { return T_ANY; } - if (_method & HTTP_GET) { + if (_method & AsyncWebRequestMethod::HTTP_GET) { return T_GET; } - if (_method & HTTP_POST) { + if (_method & AsyncWebRequestMethod::HTTP_POST) { return T_POST; } - if (_method & HTTP_DELETE) { + if (_method & AsyncWebRequestMethod::HTTP_DELETE) { return T_DELETE; } - if (_method & HTTP_PUT) { + if (_method & AsyncWebRequestMethod::HTTP_PUT) { return T_PUT; } - if (_method & HTTP_PATCH) { + if (_method & AsyncWebRequestMethod::HTTP_PATCH) { return T_PATCH; } - if (_method & HTTP_HEAD) { + if (_method & AsyncWebRequestMethod::HTTP_HEAD) { return T_HEAD; } - if (_method & HTTP_OPTIONS) { + if (_method & AsyncWebRequestMethod::HTTP_OPTIONS) { return T_OPTIONS; } - if (_method & HTTP_PROPFIND) { + if (_method & AsyncWebRequestMethod::HTTP_PROPFIND) { return T_PROPFIND; } - if (_method & HTTP_LOCK) { + if (_method & AsyncWebRequestMethod::HTTP_LOCK) { return T_LOCK; } - if (_method & HTTP_UNLOCK) { + if (_method & AsyncWebRequestMethod::HTTP_UNLOCK) { return T_UNLOCK; } - if (_method & HTTP_PROPPATCH) { + if (_method & AsyncWebRequestMethod::HTTP_PROPPATCH) { return T_PROPPATCH; } - if (_method & HTTP_MKCOL) { + if (_method & AsyncWebRequestMethod::HTTP_MKCOL) { return T_MKCOL; } - if (_method & HTTP_MOVE) { + if (_method & AsyncWebRequestMethod::HTTP_MOVE) { return T_MOVE; } - if (_method & HTTP_COPY) { + if (_method & AsyncWebRequestMethod::HTTP_COPY) { return T_COPY; } return T_UNKNOWN;