[wp-trac] [WordPress Trac] #57455: respond_to_request: store matched handlers across other methods, saving a call to get_routes().
WordPress Trac
noreply at wordpress.org
Thu Jan 12 21:35:26 UTC 2023
#57455: respond_to_request: store matched handlers across other methods, saving a
call to get_routes().
-------------------------+-----------------------------
Reporter: mreishus | Owner: (none)
Type: enhancement | Status: new
Priority: normal | Milestone: Awaiting Review
Component: REST API | Version:
Severity: normal | Keywords:
Focuses: |
-------------------------+-----------------------------
== Current Behavior
Out of the box, API requests (example: GET http://localhost:8889/wp-
json/wp/v2/posts) will make two calls to `WP_REST_Server::get_routes()`.
**Call 1**: `WP_REST_Server::dispatch()` ->
`WP_REST_Server::match_request_to_handler()` ->
`WP_REST_Server::get_routes()`.
This is the main path used when serving the request. It gets the routes,
matches to the request, then determines which handler will be used for the
request. Later, `WP_REST_Server::respond_to_request()` saves the matched
route and matched handler.
**Call 2**: `rest_send_allow_header()` -> `WP_REST_Server::get_routes()`.
This is used to set the allow header of the response (example: "Allow:
GET, POST, HEAD").
This header shows all HTTP methods that are allowed to be sent on the same
route. This information was already found in the "Call 1" pathway above,
but it was discarded.
To find the allowed headers, `rest_send_allow_header()` calls
`WP_REST_Server::get_routes()` which rebuilds information for all existing
routes (but we only need information for one route).
== Objective
To reduce the number of calls to `WP_REST_Server::get_routes()` per single
request from 2 to 1.
While this only saves 0.1ms on a fresh site, on sites with large custom
APIs, this could save 10ms or more.
== Patch
When `WP_REST_Server::match_request_to_handler()` ->
`WP_REST_Server::get_routes()` finds the matching route,
it will now not only remembers the exact matching handler, but all other
handlers matching the route with different http methods.
For example, imagine an "/a/b/c" route exists with GET and POST handlers.
Previous to the patch, `match_request_to_handler()` would find the GET
/a/b/c handler and remember it, setting it on
`$response->matched_handler`.
After the patch, a new variable `$response->all_methods_matched_handlers`
is set containing the array: [ (GET /a/b/c handler), (POST /a/b/c handler)
],
`rest_send_allow_header()` now looks for
`$response->all_methods_matched_handlers` and uses it to set the Allow
header if possible, saving a call to `WP_REST_Server::get_routes()`.
This was my way to save the information found in call 1 and to pass it
along to call 2, but I definitely open to other ideas of accomplishing the
same thing.
== Basic Testing
Add a log message when get_routes is called:
{{{#!diff
--- a/src/wp-includes/rest-api/class-wp-rest-server.php
+++ b/src/wp-includes/rest-api/class-wp-rest-server.php
@@ -862,6 +862,7 @@ class WP_REST_Server {
* `'/path/regex' => array( array( $callback,
$bitmask ), ...)`.
*/
public function get_routes( $route_namespace = '' ) {
+ error_log( 'calling get_routes' );
$endpoints = $this->endpoints;
if ( $route_namespace ) {
}}}
Query an endpoint:
`curl http://localhost:8889/wp-json/wp/v2/posts`
Before the patch: See two calls to get_routes
After the patch: See one call to get_routes
== Alternative Approaches
#39473 adds a per-request cache to get_routes. I'd be happy to rework this
if this is a better method.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/57455>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list