Repository navigation
feat: Phase 2 — route table, one handler serving multiple routes - #494
Closed
mathieucarbou wants to merge 2 commits into
Closed
mathieucarbou wants to merge 2 commits into
mathieucarbou wants to merge 2 commits into
Conversation
Give users full control over where handler objects live in memory (internal SRAM, PSRAM, static RAM) without allocator hooks or operator new overrides. Changes: - HandlerEntry struct tracks ownership explicitly (unique_ptr + raw ptr) - addHandler(ptr, takeOwnership=true) — extended with ownership flag - addHandler(ref) — non-owning reference overload for stack/static/PSRAM - AsyncWebServer(port, catchAllPtr, takeOwnership=true) — custom catch-all at construction - AsyncWebServer(port, catchAllRef) — non-owning reference overload - setCatchAllHandler(ptr, takeOwnership=true) / setCatchAllHandler(ref) - nullptr support: AsyncWebServer(port, nullptr) disables catch-all entirely; unmatched requests get a bare 501 response - catchAllHandlerPtr() — safe accessor returning nullptr instead of crashing - catchAllHandler() deprecated in favor of catchAllHandlerPtr() - onNotFound/onFileUpload/onRequestBody/reset are no-ops when no catch-all - New CustomAllocation example demonstrating static RAM, PSRAM, and server-owned handler patterns - Updated docs: routing.md, configuration.md, concepts.md Fully backward compatible: all existing APIs work unchanged. Existing sketches require zero modifications. Motivation: ESP32 internal SRAM is scarce (lwIP, WiFi buffers). Long-lived handler objects can now be moved to PSRAM or static RAM, freeing internal SRAM for networking. See discussion in #468. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Decouple URI/method matching from handler objects by introducing a
server-side routing table (RouteEntry). This enables one handler object
to serve multiple routes, combining Phase 1's ownership control with
Phase 2's routing flexibility.
Changes:
- RouteEntry struct: { AsyncURIMatcher uri, WebRequestMethodComposite method,
bool hasMatcher, HandlerEntry entry }
- addRoute(uri, method, handlerPtr, takeOwnership=true) — owning registration
- addRoute(uri, method, handlerRef) — non-owning registration
- removeRoute(uri, method) — remove a specific route
- removeHandler() now also removes routes pointing to that handler
- _attachHandler() evaluates routes first (URI+method match), then legacy
handlers (canHandle-based dispatch) — backward compatible
- AsyncCallbackWebHandler::_routeManaged flag — when set, canHandle()
skips URI/method checks (server's route table does them)
- AsyncURIMatcher::operator==/!= for route removal by value comparison
- reset() clears both _routes and _handlers
- New MultiRoute example: one handler on 3 routes (static RAM),
PSRAM handler on 2 routes, classic on() handler, custom catch-all
- Updated docs: routing.md (Route Table section), configuration.md,
concepts.md
Backward compatible: all Phase 1 APIs and existing on()/addHandler()/
serveStatic() calls work identically. Routes are additive.
Builds on #493 (Phase 1: non-owning handler registration).
Motivation from #468 discussion.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Member
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR implements Phase 2 — a route table refactoring that decouples URI/method matching from handler objects. One handler object can now serve multiple routes, combining Phase 1's ownership control with Phase 2's routing flexibility.
Builds on #493 (Phase 1: non-owning handler registration). Fully backward compatible.
Motivation
In the #468 discussion, @inF1704 pointed out that URI matching lives inside handler objects (
AsyncCallbackWebHandlercarries_uriand_method), which prevents one handler from serving multiple routes. This PR moves URI/method matching into the server's routing table.API Changes
Route Registration
server.addRoute(uri, method, new MyHandler())server.addRoute(uri, method, ptr, false)server.addRoute(uri, method, myHandler)Route Removal
server.removeRoute(uri, method)server.removeHandler(&handler)Usage
One Handler, Multiple Routes
PSRAM Handler on Multiple Routes (ESP32)
Method-Based Routing
The route table filters by HTTP method — a
GETroute won't match aPOSTrequest:Design
Internal Changes
RouteEntrystruct{ AsyncURIMatcher uri, WebRequestMethodComposite method, bool hasMatcher, HandlerEntry entry }_routesstd::list<RouteEntry>— evaluated before_handlers_attachHandler()AsyncCallbackWebHandler::_routeManagedcanHandle()skips URI/method checksAsyncURIMatcher::operator==removeRoute()removeHandler()reset()_routesand_handlersBackward Compatibility
✅ 100% additive — all existing code works identically:
server.on()/serveStatic()/addHandler()— unchangedaddHandler()usecanHandle()dispatch (legacy path)addRoute()use route table dispatch (new path)Files Changed
src/ESPAsyncWebServer.hsrc/WebServer.cppsrc/WebHandlerImpl.hsrc/WebHandlers.cppexamples/arduino/MultiRoute/MultiRoute.inodocs/routing.mddocs/configuration.mddocs/concepts.mdplatformio.iniRelated
Checklist