--- a/wp/wp-includes/rest-api.php Fri Sep 05 18:40:08 2025 +0200
+++ b/wp/wp-includes/rest-api.php Fri Sep 05 18:52:52 2025 +0200
@@ -38,26 +38,55 @@
* and namespace indexes. If you really need to register a
* non-namespaced route, call `WP_REST_Server::register_route` directly.
*/
- _doing_it_wrong( 'register_rest_route', __( 'Routes must be namespaced with plugin or theme name and version.' ), '4.4.0' );
+ _doing_it_wrong(
+ __FUNCTION__,
+ sprintf(
+ /* translators: 1: string value of the namespace, 2: string value of the route. */
+ __( 'Routes must be namespaced with plugin or theme name and version. Instead there seems to be an empty namespace \'%1$s\' for route \'%2$s\'.' ),
+ '<code>' . $route_namespace . '</code>',
+ '<code>' . $route . '</code>'
+ ),
+ '4.4.0'
+ );
return false;
} elseif ( empty( $route ) ) {
- _doing_it_wrong( 'register_rest_route', __( 'Route must be specified.' ), '4.4.0' );
+ _doing_it_wrong(
+ __FUNCTION__,
+ sprintf(
+ /* translators: 1: string value of the namespace, 2: string value of the route. */
+ __( 'Route must be specified. Instead within the namespace \'%1$s\', there seems to be an empty route \'%2$s\'.' ),
+ '<code>' . $route_namespace . '</code>',
+ '<code>' . $route . '</code>'
+ ),
+ '4.4.0'
+ );
return false;
}
$clean_namespace = trim( $route_namespace, '/' );
if ( $clean_namespace !== $route_namespace ) {
- _doing_it_wrong( __FUNCTION__, __( 'Namespace must not start or end with a slash.' ), '5.4.2' );
+ _doing_it_wrong(
+ __FUNCTION__,
+ sprintf(
+ /* translators: 1: string value of the namespace, 2: string value of the route. */
+ __( 'Namespace must not start or end with a slash. Instead namespace \'%1$s\' for route \'%2$s\' seems to contain a slash.' ),
+ '<code>' . $route_namespace . '</code>',
+ '<code>' . $route . '</code>'
+ ),
+ '5.4.2'
+ );
}
if ( ! did_action( 'rest_api_init' ) ) {
_doing_it_wrong(
- 'register_rest_route',
+ __FUNCTION__,
sprintf(
- /* translators: %s: rest_api_init */
- __( 'REST API routes must be registered on the %s action.' ),
- '<code>rest_api_init</code>'
+ /* translators: 1: rest_api_init, 2: string value of the route, 3: string value of the namespace. */
+ __( 'REST API routes must be registered on the %1$s action. Instead route \'%2$s\' with namespace \'%3$s\' was not registered on this action.' ),
+ '<code>rest_api_init</code>',
+ '<code>' . $route . '</code>',
+ '<code>' . $route_namespace . '</code>'
),
'5.1.0'
);
@@ -401,6 +430,16 @@
return;
}
+ // Return an error message if query_var is not a string.
+ if ( ! is_string( $GLOBALS['wp']->query_vars['rest_route'] ) ) {
+ $rest_type_error = new WP_Error(
+ 'rest_path_invalid_type',
+ __( 'The REST route parameter must be a string.' ),
+ array( 'status' => 400 )
+ );
+ wp_die( $rest_type_error );
+ }
+
/**
* Whether this is a REST Request.
*
@@ -789,9 +828,6 @@
}
foreach ( $endpoints as $endpoint ) {
- // Remove the redundant preg_match() argument.
- unset( $args[0] );
-
$request->set_url_params( $args );
$request->set_attributes( $endpoint );
}
@@ -1275,6 +1311,9 @@
/**
* Parses an RFC3339 time into a Unix timestamp.
*
+ * Explicitly check for `false` to detect failure, as zero is a valid return
+ * value on success.
+ *
* @since 4.4.0
*
* @param string $date RFC3339 timestamp.
@@ -1340,7 +1379,7 @@
$date = rest_parse_date( $date );
- if ( empty( $date ) ) {
+ if ( false === $date ) {
return null;
}
@@ -2230,7 +2269,7 @@
break;
case 'date-time':
- if ( ! rest_parse_date( $value ) ) {
+ if ( false === rest_parse_date( $value ) ) {
return new WP_Error( 'rest_invalid_date', __( 'Invalid date.' ) );
}
break;
@@ -2906,6 +2945,7 @@
}
}
+ // Remove trailing slashes at the end of the REST API path (query part).
$path = untrailingslashit( $path );
if ( empty( $path ) ) {
$path = '/';
@@ -2916,6 +2956,14 @@
return $memo;
}
+ if ( isset( $path_parts['path'] ) && '/' !== $path_parts['path'] ) {
+ // Remove trailing slashes from the "path" part of the REST API path.
+ $path_parts['path'] = untrailingslashit( $path_parts['path'] );
+ $path = str_contains( $path, '?' ) ?
+ $path_parts['path'] . '?' . ( $path_parts['query'] ?? '' ) :
+ $path_parts['path'];
+ }
+
$request = new WP_REST_Request( $method, $path_parts['path'] );
if ( ! empty( $path_parts['query'] ) ) {
parse_str( $path_parts['query'], $query_params );