Make WordPress Core


Ignore:
Timestamp:
03/02/2025 10:05:08 PM (3 months ago)
Author:
TimothyBlynJacobs
Message:

REST API: Improve performance for HEAD requests.

By default, the REST API responds to HEAD rqeuests by calling the GET handler and omitting the body from the response. While convenient, this ends up performing needless work that slows down the API response time.

This commit adjusts the Core controllers to specifically handle HEAD requests by not preparing the response body.

Fixes #56481.
Props antonvlasenko, janusdev, ironprogrammer, swissspidy, spacedmonkey, mukesh27, mamaduka, timothyblynjacobs.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/rest-api/rest-pattern-directory-controller.php

    r56559 r59899  
    146146
    147147    /**
     148     * @ticket 56481
     149     */
     150    public function test_get_items_with_head_request_should_not_prepare_block_patterns_data() {
     151        wp_set_current_user( self::$contributor_id );
     152        self::mock_successful_response( 'browse-all', true );
     153
     154        $request = new WP_REST_Request( 'HEAD', '/wp/v2/pattern-directory/patterns' );
     155
     156        $hook_name = 'rest_prepare_block_pattern';
     157        $filter    = new MockAction();
     158        $callback  = array( $filter, 'filter' );
     159
     160        add_filter( $hook_name, $callback );
     161        $response = rest_get_server()->dispatch( $request );
     162        remove_filter( $hook_name, $callback );
     163
     164        $this->assertNotWPError( $response );
     165        $response = rest_ensure_response( $response );
     166
     167        $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
     168
     169        $this->assertSame( 0, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' );
     170        $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
     171    }
     172
     173    /**
    148174     * @covers WP_REST_Pattern_Directory_Controller::get_items
    149175     *
     
    220246
    221247    /**
    222      * @covers WP_REST_Pattern_Directory_Controller::get_items
    223      *
    224      * @since 5.8.0
    225      */
    226     public function test_get_items_wdotorg_unavailable() {
     248     * @dataProvider data_readable_http_methods
     249     * @ticket 56481
     250     *
     251     * @covers WP_REST_Pattern_Directory_Controller::get_items
     252     *
     253     * @since 5.8.0
     254     *
     255     * @param string $method The HTTP method to use.
     256     */
     257    public function test_get_items_wdotorg_unavailable( $method ) {
    227258        wp_set_current_user( self::$contributor_id );
    228259        self::prevent_requests_to_host( 'api.wordpress.org' );
    229260
    230         $request  = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' );
     261        $request  = new WP_REST_Request( $method, '/wp/v2/pattern-directory/patterns' );
    231262        $response = rest_do_request( $request );
    232263
     
    235266
    236267    /**
    237      * @covers WP_REST_Pattern_Directory_Controller::get_items
    238      *
    239      * @since 5.8.0
    240      */
    241     public function test_get_items_logged_out() {
    242         $request = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' );
     268     * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
     269     *
     270     * @return array
     271     */
     272    public static function data_readable_http_methods() {
     273        return array(
     274            'GET request'  => array( 'GET' ),
     275            'HEAD request' => array( 'HEAD' ),
     276        );
     277    }
     278
     279    /**
     280     * @dataProvider data_readable_http_methods
     281     * @ticket 56481
     282     *
     283     * @covers WP_REST_Pattern_Directory_Controller::get_items
     284     *
     285     * @since 5.8.0
     286     *
     287     * @param string $method The HTTP method to use.
     288     */
     289    public function test_get_items_logged_out( $method ) {
     290        $request = new WP_REST_Request( $method, '/wp/v2/pattern-directory/patterns' );
    243291        $request->set_query_params( array( 'search' => 'button' ) );
    244292        $response = rest_do_request( $request );
     
    284332
    285333    /**
    286      * @covers WP_REST_Pattern_Directory_Controller::get_items
    287      *
    288      * @since 5.8.0
    289      */
    290     public function test_get_items_invalid_response_data() {
     334     * @dataProvider data_readable_http_methods
     335     * @ticket 56481
     336     *
     337     * @covers WP_REST_Pattern_Directory_Controller::get_items
     338     *
     339     * @since 5.8.0
     340     *
     341     * @param string $method The HTTP method to use.
     342     */
     343    public function test_get_items_invalid_response_data( $method ) {
    291344        wp_set_current_user( self::$contributor_id );
    292345        self::mock_successful_response( 'invalid-data', true );
    293346
    294         $request  = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' );
     347        $request  = new WP_REST_Request( $method, '/wp/v2/pattern-directory/patterns' );
    295348        $response = rest_do_request( $request );
    296349
Note: See TracChangeset for help on using the changeset viewer.