Skip to content

Commit 2377580

Browse files
willmmilesGitHub Copilotmathieucarbou
committed
Handle collisions with other webservers
Fix HTTP_ANY macro conflict with Arduino core. Rename the combination value to HTTP_ALL and make it type-safe as a WebRequestMethodComposite. Ensure a warning is generated when conflicts are detected, and add a deprecation alert to our compatibility HTTP_ANY value. Co-authored-by: GitHub Copilot <copilot@github.com> Co-authored-by: mathieucarbou <61346+mathieucarbou@users.noreply.github.com>
1 parent 70acb12 commit 2377580

6 files changed

Lines changed: 56 additions & 34 deletions

File tree

docs/backup/wiki.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,7 +1887,7 @@ void setup(){
18871887
}, onUpload);
18881888

18891889
// send a file when /index is requested
1890-
server.on("/index", HTTP_ANY, [](AsyncWebServerRequest *request){
1890+
server.on("/index", HTTP_ALL, [](AsyncWebServerRequest *request){
18911891
request->send(SPIFFS, "/index.htm");
18921892
});
18931893

@@ -1974,10 +1974,10 @@ public :
19741974
19751975
void begin(){
19761976
// attach global request handler
1977-
classWebServer.on("/example", HTTP_ANY, handleRequest);
1977+
classWebServer.on("/example", HTTP_ALL, handleRequest);
19781978
19791979
// attach class request handler
1980-
classWebServer.on("/example", HTTP_ANY, std::bind(&WebClass::classRequest, this, std::placeholders::_1));
1980+
classWebServer.on("/example", HTTP_ALL, std::bind(&WebClass::classRequest, this, std::placeholders::_1));
19811981
}
19821982
};
19831983
@@ -1986,10 +1986,10 @@ WebClass webClassInstance;
19861986
19871987
void setup() {
19881988
// attach global request handler
1989-
globalWebServer.on("/example", HTTP_ANY, handleRequest);
1989+
globalWebServer.on("/example", HTTP_ALL, handleRequest);
19901990
19911991
// attach class request handler
1992-
globalWebServer.on("/example", HTTP_ANY, std::bind(&WebClass::classRequest, webClassInstance, std::placeholders::_1));
1992+
globalWebServer.on("/example", HTTP_ALL, std::bind(&WebClass::classRequest, webClassInstance, std::placeholders::_1));
19931993
}
19941994
19951995
void loop() {

docs/setup.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,12 @@ void setup(){
7171
}, onUpload);
7272

7373
// send a file when /index is requested (SPIFFS example)
74-
server.on("/index", HTTP_ANY, [](AsyncWebServerRequest *request){
74+
server.on("/index", HTTP_ALL, [](AsyncWebServerRequest *request){
7575
request->send(SPIFFS, "/index.htm");
7676
});
7777

7878
// send a file when /index is requested (LittleFS example)
79-
server.on("/index", HTTP_ANY, [](AsyncWebServerRequest *request){
79+
server.on("/index", HTTP_ALL, [](AsyncWebServerRequest *request){
8080
request->send(LittleFS, "/index.htm");
8181
});
8282

@@ -161,10 +161,10 @@ public :
161161
162162
void begin(){
163163
// attach global request handler
164-
classWebServer.on("/example", HTTP_ANY, handleRequest);
164+
classWebServer.on("/example", HTTP_ALL, handleRequest);
165165
166166
// attach class request handler
167-
classWebServer.on("/example", HTTP_ANY, std::bind(&WebClass::classRequest, this, std::placeholders::_1));
167+
classWebServer.on("/example", HTTP_ALL, std::bind(&WebClass::classRequest, this, std::placeholders::_1));
168168
}
169169
};
170170
@@ -173,10 +173,10 @@ WebClass webClassInstance;
173173
174174
void setup() {
175175
// attach global request handler
176-
globalWebServer.on("/example", HTTP_ANY, handleRequest);
176+
globalWebServer.on("/example", HTTP_ALL, handleRequest);
177177
178178
// attach class request handler
179-
globalWebServer.on("/example", HTTP_ANY, std::bind(&WebClass::classRequest, webClassInstance, std::placeholders::_1));
179+
globalWebServer.on("/example", HTTP_ALL, std::bind(&WebClass::classRequest, webClassInstance, std::placeholders::_1));
180180
}
181181
182182
void loop() {

src/ESPAsyncWebServer.h

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,19 @@
6666
#define ASYNCWEBSERVER_WIFI_SUPPORTED 0
6767
#endif
6868

69+
// HTTP_ANY is commonly defined as a macro in Arduino core HTTP client libraries (e.g., ESP8266 HTTPClient.h).
70+
// Macros are expanded by the preprocessor before C++ namespace resolution, so even a namespace-qualified
71+
// reference like AsyncWebRequestMethod::HTTP_ANY would be incorrectly expanded to AsyncWebRequestMethod::0.
72+
// In these cases, other HTTP_METHOD symbols will likely also become ambiguous if put in the global namespace.
73+
// To avoid these conflicts, AsyncWebRequestMethod::HTTP_ANY will only be provided if no conflicting definition
74+
// is present; and we will disable putting our definitions in the global namespace.
75+
// If the user explicitly defined ASYNCWEBSERVER_NO_GLOBAL_HTTP_METHODS, we assume they are using safely
76+
// namespaced references and AsyncWebServerMethod::HTTP_ALL.
77+
#if defined(HTTP_ANY) && !defined(ASYNCWEBSERVER_NO_GLOBAL_HTTP_METHODS)
78+
#warning HTTP_ANY definition collision detected - AsyncWebServer HTTP_ methods will not be defined in the global namespace. Make sure to use AsyncWebServerMethod::HTTP_ALL instead, and define ASYNCWEBSERVER_NO_GLOBAL_HTTP_METHODS to disable this warning.
79+
#define ASYNCWEBSERVER_NO_GLOBAL_HTTP_METHODS
80+
#endif
81+
6982
class AsyncWebServer;
7083
class AsyncWebServerRequest;
7184
class AsyncWebServerResponse;
@@ -82,29 +95,40 @@ class AsyncMiddlewareChain;
8295
namespace AsyncWebRequestMethod {
8396
// The long name here is because we sometimes include this in the global namespace
8497
enum AsyncWebRequestMethodType {
85-
HTTP_GET = 0b0000000000000001,
86-
HTTP_POST = 0b0000000000000010,
87-
HTTP_DELETE = 0b0000000000000100,
88-
HTTP_PUT = 0b0000000000001000,
89-
HTTP_PATCH = 0b0000000000010000,
90-
HTTP_HEAD = 0b0000000000100000,
91-
HTTP_OPTIONS = 0b0000000001000000,
92-
HTTP_PROPFIND = 0b0000000010000000,
93-
HTTP_LOCK = 0b0000000100000000,
94-
HTTP_UNLOCK = 0b0000001000000000,
95-
HTTP_PROPPATCH = 0b0000010000000000,
96-
HTTP_MKCOL = 0b0000100000000000,
97-
HTTP_MOVE = 0b0001000000000000,
98-
HTTP_COPY = 0b0010000000000000,
99-
HTTP_RESERVED = 0b0100000000000000,
100-
HTTP_ANY = 0b0111111111111111,
101-
HTTP_INVALID = 0b1000000000000000
98+
HTTP_GET = 1 << 0,
99+
HTTP_POST = 1 << 1,
100+
HTTP_DELETE = 1 << 2,
101+
HTTP_PUT = 1 << 3,
102+
HTTP_PATCH = 1 << 4,
103+
HTTP_HEAD = 1 << 5,
104+
HTTP_OPTIONS = 1 << 6,
105+
HTTP_PROPFIND = 1 << 7,
106+
HTTP_LOCK = 1 << 8,
107+
HTTP_UNLOCK = 1 << 9,
108+
HTTP_PROPPATCH = 1 << 10,
109+
HTTP_MKCOL = 1 << 11,
110+
HTTP_MOVE = 1 << 12,
111+
HTTP_COPY = 1 << 13,
112+
HTTP_RESERVED = 1 << 14,
113+
114+
HTTP_UNKNOWN = 0,
115+
HTTP_INVALID = 1 << 15 // Sentinel
102116
};
103117
}; // namespace AsyncWebRequestMethod
104118

105119
typedef AsyncWebRequestMethod::AsyncWebRequestMethodType WebRequestMethod;
106120
typedef uint16_t WebRequestMethodComposite;
107121

122+
namespace AsyncWebRequestMethod {
123+
constexpr WebRequestMethodComposite HTTP_ALL = static_cast<WebRequestMethodComposite>(HTTP_INVALID) - 1;
124+
125+
// We used to use HTTP_ANY but some libraries squat on this name with a macro. Transition to HTTP_ALL instead.
126+
#ifndef HTTP_ANY
127+
__attribute__((deprecated("HTTP_ANY is used as a macro by other libraries - use AsyncWebRequestMethod::HTTP_ALL instead."))
128+
) constexpr WebRequestMethodComposite HTTP_ANY = HTTP_ALL;
129+
#endif
130+
} // namespace AsyncWebRequestMethod
131+
108132
// Type-safe helper functions for composite methods
109133
constexpr inline WebRequestMethodComposite operator|(WebRequestMethodComposite l, WebRequestMethod r) {
110134
return l | static_cast<WebRequestMethodComposite>(r);
@@ -1566,7 +1590,7 @@ class AsyncWebServer : public AsyncMiddlewareChain {
15661590
bool removeHandler(AsyncWebHandler *handler);
15671591

15681592
AsyncCallbackWebHandler &on(AsyncURIMatcher uri, ArRequestHandlerFunction onRequest) {
1569-
return on(std::move(uri), AsyncWebRequestMethod::HTTP_ANY, onRequest);
1593+
return on(std::move(uri), AsyncWebRequestMethod::HTTP_ALL, onRequest);
15701594
}
15711595
AsyncCallbackWebHandler &on(
15721596
AsyncURIMatcher uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload = nullptr,

src/WebHandlerImpl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class AsyncCallbackWebHandler : public AsyncWebHandler {
6262
bool _isRegex;
6363

6464
public:
65-
AsyncCallbackWebHandler() : _uri(), _method(AsyncWebRequestMethod::HTTP_ANY), _onRequest(NULL), _onUpload(NULL), _onBody(NULL), _isRegex(false) {}
65+
AsyncCallbackWebHandler() : _uri(), _method(AsyncWebRequestMethod::HTTP_ALL), _onRequest(NULL), _onUpload(NULL), _onBody(NULL), _isRegex(false) {}
6666
void setUri(AsyncURIMatcher uri);
6767
void setMethod(WebRequestMethodComposite method) {
6868
_method = method;

src/WebRequest.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ enum {
4040

4141
AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer *s, AsyncClient *c)
4242
: _client(c), _server(s), _handler(NULL), _response(NULL), _onDisconnectfn(NULL), _temp(), _parseState(PARSE_REQ_START), _version(0),
43-
_method(AsyncWebRequestMethod::HTTP_ANY), _url(), _host(), _contentType(), _boundary(), _authorization(), _reqconntype(RCT_HTTP),
43+
_method(AsyncWebRequestMethod::HTTP_UNKNOWN), _url(), _host(), _contentType(), _boundary(), _authorization(), _reqconntype(RCT_HTTP),
4444
_authMethod(AsyncAuthType::AUTH_NONE), _isMultipart(false), _isPlainPost(false), _expectingContinue(false), _contentLength(0), _parsedLength(0),
4545
_multiParseState(0), _boundaryPosition(0), _itemStartIndex(0), _itemSize(0), _itemName(), _itemFilename(), _itemType(), _itemValue(), _itemBuffer(0),
4646
_itemBufferIndex(0), _itemIsFile(false), _chunkStartIndex(0), _chunkOffset(0), _chunkSize(0), _chunkedParseState(CHUNK_NONE), _chunkedLastChar(0),
@@ -1357,7 +1357,6 @@ const char *methodToString(WebRequestMethod method) {
13571357
case AsyncWebRequestMethod::HTTP_MKCOL: return T_MKCOL;
13581358
case AsyncWebRequestMethod::HTTP_MOVE: return T_MOVE;
13591359
case AsyncWebRequestMethod::HTTP_COPY: return T_COPY;
1360-
case AsyncWebRequestMethod::HTTP_ANY: return T_ANY;
1361-
default: return T_UNKNOWN;
1360+
default: return T_UNKNOWN;
13621361
}
13631362
}

src/literals.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ static constexpr const char T_WWW_AUTH[] = "WWW-Authenticate";
104104
static constexpr const char T_X_Expected_Entity_Length[] = "X-Expected-Entity-Length";
105105

106106
// HTTP Methods
107-
static constexpr const char T_ANY[] = "ANY";
108107
static constexpr const char T_GET[] = "GET";
109108
static constexpr const char T_POST[] = "POST";
110109
static constexpr const char T_PUT[] = "PUT";

0 commit comments

Comments
 (0)