Skip to content

Commit 28cd2b2

Browse files
committed
Improve external HTTP method integration
1 parent a251ca5 commit 28cd2b2

3 files changed

Lines changed: 76 additions & 29 deletions

File tree

src/AsyncJson.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ AsyncCallbackJsonWebHandler::AsyncCallbackJsonWebHandler(AsyncURIMatcher uri, Ar
124124
#endif
125125

126126
bool AsyncCallbackJsonWebHandler::canHandle(AsyncWebServerRequest *request) const {
127-
if (!_onRequest || !request->isHTTP() || !asyncsrv::methodMatches(_method, request->method())) {
127+
if (!_onRequest || !request->isHTTP() || !_method.matches(request->method())) {
128128
return false;
129129
}
130130

src/ESPAsyncWebServer.h

Lines changed: 74 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,9 @@
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 AsyncWebRequestMethod::HTTP_ALL instead, and define ASYNCWEBSERVER_NO_GLOBAL_HTTP_METHODS to disable this warning.
69+
// Enable integration with other HTTP libraries
70+
#if defined(HTTP_ANY) || defined(http_parser_h)
71+
#define ASYNCWEBSERVER_HTTP_METHOD_INTEGRATION
7972
#define ASYNCWEBSERVER_NO_GLOBAL_HTTP_METHODS
8073
#endif
8174

@@ -150,13 +143,80 @@ enum AsyncWebRequestMethodType {
150143

151144
HTTP_INVALID = 1 << 31 // Sentinel
152145
};
146+
153147
}; // namespace AsyncWebRequestMethod
154148

155149
typedef AsyncWebRequestMethod::AsyncWebRequestMethodType WebRequestMethod;
156-
typedef uint32_t WebRequestMethodComposite;
150+
class WebRequestMethodComposite {
151+
uint32_t mask;
152+
153+
private:
154+
constexpr WebRequestMethodComposite(uint32_t m) : mask(m){};
155+
156+
public:
157+
// Constructor: allows implicit conversion from WebRequestMethod
158+
constexpr WebRequestMethodComposite(WebRequestMethod m) : mask(static_cast<uint32_t>(m)){};
159+
160+
// Combine composites
161+
constexpr inline WebRequestMethodComposite operator|(WebRequestMethodComposite r) {
162+
return mask | r.mask;
163+
};
164+
165+
// Check for a match
166+
constexpr inline bool matches(WebRequestMethod m) const {
167+
return mask & static_cast<uint32_t>(m);
168+
};
169+
170+
constexpr inline bool operator&(WebRequestMethod m) const {
171+
return matches(m);
172+
}
173+
174+
// Super cool feature: integration with platform `http_method` enum
175+
#ifdef ASYNCWEBSERVER_HTTP_METHOD_INTEGRATION
176+
177+
// Conversion function for integration with external libraries.
178+
// Horrible ternary implementation for C++11 compatibility.
179+
#define MAP_EXTERNAL_TERNARY(x) (t == http_method::x) ? static_cast<uint32_t>(WebRequestMethod::x)
180+
constexpr static inline uint32_t map_http_method(http_method t) {
181+
return MAP_EXTERNAL_TERNARY(HTTP_DELETE)
182+
: MAP_EXTERNAL_TERNARY(HTTP_GET)
183+
: MAP_EXTERNAL_TERNARY(HTTP_HEAD)
184+
: MAP_EXTERNAL_TERNARY(HTTP_POST)
185+
: MAP_EXTERNAL_TERNARY(HTTP_PUT)
186+
: MAP_EXTERNAL_TERNARY(HTTP_CONNECT)
187+
: MAP_EXTERNAL_TERNARY(HTTP_OPTIONS)
188+
: MAP_EXTERNAL_TERNARY(HTTP_TRACE)
189+
: MAP_EXTERNAL_TERNARY(HTTP_COPY)
190+
: MAP_EXTERNAL_TERNARY(HTTP_LOCK)
191+
: MAP_EXTERNAL_TERNARY(HTTP_MKCOL)
192+
: MAP_EXTERNAL_TERNARY(HTTP_MOVE)
193+
: MAP_EXTERNAL_TERNARY(HTTP_PROPFIND)
194+
: MAP_EXTERNAL_TERNARY(HTTP_PROPPATCH)
195+
: MAP_EXTERNAL_TERNARY(HTTP_SEARCH)
196+
: MAP_EXTERNAL_TERNARY(HTTP_UNLOCK)
197+
: MAP_EXTERNAL_TERNARY(HTTP_BIND)
198+
: MAP_EXTERNAL_TERNARY(HTTP_REBIND)
199+
: MAP_EXTERNAL_TERNARY(HTTP_UNBIND)
200+
: MAP_EXTERNAL_TERNARY(HTTP_ACL)
201+
: MAP_EXTERNAL_TERNARY(HTTP_PATCH)
202+
: MAP_EXTERNAL_TERNARY(HTTP_PURGE)
203+
: MAP_EXTERNAL_TERNARY(HTTP_LINK)
204+
: MAP_EXTERNAL_TERNARY(HTTP_UNLINK)
205+
: (t == HTTP_ANY) ? static_cast<uint32_t>(WebRequestMethod::HTTP_INVALID) - 1 : static_cast<uint32_t>(WebRequestMethod::HTTP_INVALID);
206+
}
207+
#undef MAP_EXTERNAL_TERNARY
208+
209+
constexpr WebRequestMethodComposite(http_method m) : mask(map_http_method(m)){};
210+
#endif
211+
}; // WebRequestMethodComposite
212+
213+
// Operator| for WebRequestMethod: combine to a WebRequestMethodComposite
214+
constexpr inline WebRequestMethodComposite operator|(WebRequestMethod l, WebRequestMethod r) {
215+
return static_cast<WebRequestMethodComposite>(l) | r;
216+
};
157217

158218
namespace AsyncWebRequestMethod {
159-
constexpr WebRequestMethodComposite HTTP_ALL = static_cast<WebRequestMethodComposite>(HTTP_INVALID) - 1;
219+
constexpr WebRequestMethodComposite HTTP_ALL = static_cast<WebRequestMethod>(static_cast<uint32_t>(HTTP_INVALID) - 1);
160220

161221
// We used to use HTTP_ANY but some libraries squat on this name with a macro. Transition to HTTP_ALL instead.
162222
#ifndef HTTP_ANY
@@ -165,24 +225,11 @@ __attribute__((deprecated("HTTP_ANY is used as a macro by other libraries - use
165225
#endif
166226
} // namespace AsyncWebRequestMethod
167227

168-
// Type-safe helper functions for composite methods
169-
constexpr inline WebRequestMethodComposite operator|(WebRequestMethodComposite l, WebRequestMethod r) {
170-
return l | static_cast<WebRequestMethodComposite>(r);
171-
};
172-
constexpr inline WebRequestMethodComposite operator|(WebRequestMethod l, WebRequestMethod r) {
173-
return static_cast<WebRequestMethodComposite>(l) | r;
174-
};
175-
176-
namespace asyncsrv {
177-
// utility method to check if a WebRequestMethod matches a WebRequestMethodComposite
178-
constexpr inline bool methodMatches(WebRequestMethodComposite c, WebRequestMethod m) {
179-
return c & static_cast<WebRequestMethodComposite>(m);
180-
};
181-
182228
// WebRequestMethod string conversion functions
229+
namespace asyncsrv {
183230
WebRequestMethod stringToMethod(const String &);
184231
const char *methodToString(WebRequestMethod);
185-
} // namespace asyncsrv
232+
} // namespace asyncsrv
186233

187234
#if !defined(ASYNCWEBSERVER_NO_GLOBAL_HTTP_METHODS)
188235
// Import the method enum values to the global namespace

src/WebHandlers.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ void AsyncCallbackWebHandler::setUri(AsyncURIMatcher uri) {
300300
}
301301

302302
bool AsyncCallbackWebHandler::canHandle(AsyncWebServerRequest *request) const {
303-
if (!_onRequest || !request->isHTTP() || !asyncsrv::methodMatches(_method, request->method())) {
303+
if (!_onRequest || !request->isHTTP() || !_method.matches(request->method())) {
304304
return false;
305305
}
306306
return _uri.matches(request);

0 commit comments

Comments
 (0)