[wp-trac] [WordPress Trac] #63946: Introduce a mechanism for lazy-loading REST routes and handlers

WordPress Trac noreply at wordpress.org
Wed Mar 25 21:09:43 UTC 2026


#63946: Introduce a mechanism for lazy-loading REST routes and handlers
--------------------------------------+------------------------------
 Reporter:  prettyboymp               |       Owner:  (none)
     Type:  enhancement               |      Status:  new
 Priority:  normal                    |   Milestone:  Awaiting Review
Component:  REST API                  |     Version:
 Severity:  normal                    |  Resolution:
 Keywords:  has-patch has-unit-tests  |     Focuses:  performance
--------------------------------------+------------------------------

Comment (by prettyboymp):

 @rmccue I actually explored the callable `$args` approach initially before
 landing on namespace-level lazy loading, but I hit some backward
 compatibility issues.

 1. **`rest_endpoints` filter**: `get_routes()` passes `$this->endpoints`
 through this filter (line 968). Plugins iterating the filtered data expect
 arrays, not Closures — storing Closures in `$this->endpoints` would break
 them.

 2. **`rest_send_allow_header()`**: Calls `$server->get_routes()` without a
 namespace parameter on every REST response (line 880), which would force
 resolution of all Closures, not just the matched route's. This also runs
 per-item via `get_target_hints_for_link()` in collection responses.

 On the point that "registering the namespaces and their routes isn't
 expensive, rather it's the argument building that's slow" — the
 registration itself is cheap, but having more entries in
 `$this->endpoints` has a per-request cost beyond route matching.
 `rest_send_allow_header()` calls `get_routes()` without a namespace
 parameter (line 880), so on every REST response the full endpoints array
 is copied, passed through the `rest_endpoints` filter, and normalized
 (lines 979-1016). This also runs per-item via
 `get_target_hints_for_link()` in collection responses. Every registered
 route — even ones whose namespace doesn't match the current request — adds
 to that cost.

 I do like the callable approach as a cleaner implementation — I just don't
 know if we can get away with breaking the expectation of what's passed
 through the `rest_endpoints` filter. The namespace approach sidesteps that
 entirely because lazy namespaces never enter `$this->endpoints` until
 fully loaded.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/63946#comment:8>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list