REST API: Match REST API routes on namespace before performing regex checks.

Rule out groups of API endpoints by simple namespace string comparison to reduce the number of regex checks necessary when matching a route.

Props TimothyBlynJacobs.
Fixes #48530.


git-svn-id: https://develop.svn.wordpress.org/trunk@47260 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
K. Adam White 2020-02-11 03:20:05 +00:00
parent 3125c21cc4
commit fc434a0c77
2 changed files with 34 additions and 3 deletions

View File

@ -744,11 +744,18 @@ class WP_REST_Server {
* used as the delimiter with preg_match()
*
* @since 4.4.0
* @since 5.4.0 Add $namespace parameter.
*
* @param string $namespace Optionally, only return routes in the given namespace.
* @return array `'/path/regex' => array( $callback, $bitmask )` or
* `'/path/regex' => array( array( $callback, $bitmask ), ...)`.
*/
public function get_routes() {
public function get_routes( $namespace = '' ) {
$endpoints = $this->endpoints;
if ( $namespace ) {
$endpoints = wp_list_filter( $endpoints, array( 'namespace' => $namespace ) );
}
/**
* Filters the array of available endpoints.
@ -760,7 +767,7 @@ class WP_REST_Server {
* `'/path/regex' => array( $callback, $bitmask )` or
* `'/path/regex' => array( array( $callback, $bitmask ).
*/
$endpoints = apply_filters( 'rest_endpoints', $this->endpoints );
$endpoints = apply_filters( 'rest_endpoints', $endpoints );
// Normalise the endpoints.
$defaults = array(
@ -872,7 +879,20 @@ class WP_REST_Server {
$method = $request->get_method();
$path = $request->get_route();
foreach ( $this->get_routes() as $route => $handlers ) {
$routes = array();
foreach ( $this->get_namespaces() as $namespace ) {
if ( 0 === strpos( ltrim( $path, '/' ), $namespace ) ) {
$routes = $this->get_routes( $namespace );
break;
}
}
if ( ! $routes ) {
$routes = $this->get_routes();
}
foreach ( $routes as $route => $handlers ) {
$match = preg_match( '@^' . $route . '$@i', $path, $matches );
if ( ! $match ) {

View File

@ -1431,6 +1431,17 @@ class Tests_REST_Server extends WP_Test_REST_TestCase {
);
}
/**
* @ticket 48530
*/
public function test_get_routes_respects_namespace_parameter() {
$routes = rest_get_server()->get_routes( 'oembed/1.0' );
foreach ( $routes as $route => $handlers ) {
$this->assertStringStartsWith( '/oembed/1.0', $route );
}
}
public function _validate_as_integer_123( $value, $request, $key ) {
if ( ! is_int( $value ) ) {
return new WP_Error( 'some-error', 'This is not valid!' );