Index: wp-includes/rest-api/class-wp-rest-server.php
====================================================
--- wp-includes/rest-api/class-wp-rest-server.php
+++ wp-includes/rest-api/class-wp-rest-server.php
@@ -828,6 +828,23 @@ class WP_REST_Server {
 					}
 				}
 
+				$did_run_before_callbacks = false;
+				if ( ! is_wp_error( $response ) ) {
+					/**
+					 * Call a filter before executing any callbacks.  Allows
+					 * plugins to perform additional validation after a request
+					 * is initialized but before it is executed.
+					 *
+					 * @since 4.4.2
+					 *
+					 * @param WP_HTTP_Response $response Result to send to the client. Usually a WP_REST_Response.
+					 * @param WP_REST_Server   $handler  ResponseHandler instance (usually WP_REST_Server).
+					 * @param WP_REST_Request  $request  Request used to generate the response.
+					 */
+					$response = apply_filters( 'rest_request_before_callbacks', $response, $handler, $request );
+					$did_run_before_callbacks = true;
+				}
+
 				if ( ! is_wp_error( $response ) ) {
 					// Check permission specified on the route.
 					if ( ! empty( $handler['permission_callback'] ) ) {
@@ -862,6 +879,22 @@ class WP_REST_Server {
 					}
 				}
 
+				if ( $did_run_before_callbacks ) {
+					/**
+					 * Call a filter immediately after executing the request
+					 * callback(s).  Allows plugins to perform any needed
+					 * cleanup, for example, to undo changes made by
+					 * `rest_request_before_callbacks`.
+					 *
+					 * @since 4.4.2
+					 *
+					 * @param WP_HTTP_Response $response Result to send to the client. Usually a WP_REST_Response.
+					 * @param WP_REST_Server   $handler  ResponseHandler instance (usually WP_REST_Server).
+					 * @param WP_REST_Request  $request  Request used to generate the response.
+					 */
+					$response = apply_filters( 'rest_request_after_callbacks', $response, $handler, $request );
+				}
+
 				if ( is_wp_error( $response ) ) {
 					$response = $this->error_to_response( $response );
 				} else {
