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-block-type-controller.php

    r57565 r59899  
    603603
    604604    /**
    605      * @ticket 47620
    606      */
    607     public function test_get_items_wrong_permission() {
     605     * @dataProvider data_readable_http_methods
     606     * @ticket 56481
     607     *
     608     * @param string $method The HTTP method to use.
     609     */
     610    public function test_get_item_should_allow_adding_headers_via_filter( $method ) {
     611        $block_name = 'fake/test';
     612        wp_set_current_user( self::$admin_id );
     613
     614        $hook_name = 'rest_prepare_block_type';
     615        $filter    = new MockAction();
     616        $callback  = array( $filter, 'filter' );
     617        add_filter( $hook_name, $callback );
     618        $header_filter = new class() {
     619            public static function add_custom_header( $response ) {
     620                $response->header( 'X-Test-Header', 'Test' );
     621
     622                return $response;
     623            }
     624        };
     625        add_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
     626        $request  = new WP_REST_Request( $method, '/wp/v2/block-types/' . $block_name );
     627        $response = rest_get_server()->dispatch( $request );
     628        remove_filter( $hook_name, $callback );
     629        remove_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
     630
     631        $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
     632        $this->assertSame( 1, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' );
     633        $headers = $response->get_headers();
     634        $this->assertArrayHasKey( 'X-Test-Header', $headers, 'The "X-Test-Header" header should be present in the response.' );
     635        $this->assertSame( 'Test', $headers['X-Test-Header'], 'The "X-Test-Header" header value should be equal to "Test".' );
     636        if ( 'HEAD' !== $method ) {
     637            return null;
     638        }
     639        $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
     640    }
     641
     642    /**
     643     * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
     644     *
     645     * @return array
     646     */
     647    public static function data_readable_http_methods() {
     648        return array(
     649            'GET request'  => array( 'GET' ),
     650            'HEAD request' => array( 'HEAD' ),
     651        );
     652    }
     653
     654    /**
     655     * @ticket 56481
     656     */
     657    public function test_get_items_with_head_request_should_not_prepare_block_type_data() {
     658        wp_set_current_user( self::$admin_id );
     659        $request  = new WP_REST_Request( 'HEAD', '/wp/v2/block-types' );
     660        $response = rest_get_server()->dispatch( $request );
     661        $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
     662        $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
     663    }
     664
     665    /**
     666     * @dataProvider data_readable_http_methods
     667     * @ticket 47620
     668     * @ticket 56481
     669     *
     670     * @param string $method HTTP method to use.
     671     */
     672    public function test_get_items_wrong_permission( $method ) {
    608673        wp_set_current_user( self::$subscriber_id );
    609         $request  = new WP_REST_Request( 'GET', '/wp/v2/block-types' );
     674        $request  = new WP_REST_Request( $method, '/wp/v2/block-types' );
    610675        $response = rest_get_server()->dispatch( $request );
    611676        $this->assertErrorResponse( 'rest_block_type_cannot_view', $response, 403 );
     
    613678
    614679    /**
    615      * @ticket 47620
    616      */
    617     public function test_get_item_wrong_permission() {
     680     * @dataProvider data_readable_http_methods
     681     * @ticket 47620
     682     * @ticket 56481
     683     *
     684     * @param string $method HTTP method to use.
     685     */
     686    public function test_get_item_wrong_permission( $method ) {
    618687        wp_set_current_user( self::$subscriber_id );
    619         $request  = new WP_REST_Request( 'GET', '/wp/v2/block-types/fake/test' );
     688        $request  = new WP_REST_Request( $method, '/wp/v2/block-types/fake/test' );
    620689        $response = rest_get_server()->dispatch( $request );
    621690        $this->assertErrorResponse( 'rest_block_type_cannot_view', $response, 403 );
     
    623692
    624693    /**
    625      * @ticket 47620
    626      */
    627     public function test_get_items_no_permission() {
     694     * @dataProvider data_readable_http_methods
     695     * @ticket 47620
     696     * @ticket 56481
     697     *
     698     * @param string $method HTTP method to use.
     699     */
     700    public function test_get_items_no_permission( $method ) {
    628701        wp_set_current_user( 0 );
    629         $request  = new WP_REST_Request( 'GET', '/wp/v2/block-types' );
     702        $request  = new WP_REST_Request( $method, '/wp/v2/block-types' );
    630703        $response = rest_get_server()->dispatch( $request );
    631704        $this->assertErrorResponse( 'rest_block_type_cannot_view', $response, 401 );
     
    633706
    634707    /**
    635      * @ticket 47620
    636      */
    637     public function test_get_item_no_permission() {
     708     * @dataProvider data_readable_http_methods
     709     * @ticket 47620
     710     * @ticket 56481
     711     *
     712     * @param string $method HTTP method to use.
     713     */
     714    public function test_get_item_no_permission( $method ) {
    638715        wp_set_current_user( 0 );
    639         $request  = new WP_REST_Request( 'GET', '/wp/v2/block-types/fake/test' );
     716        $request  = new WP_REST_Request( $method, '/wp/v2/block-types/fake/test' );
    640717        $response = rest_get_server()->dispatch( $request );
    641718        $this->assertErrorResponse( 'rest_block_type_cannot_view', $response, 401 );
     
    643720
    644721    /**
    645      * @ticket 47620
     722     * @dataProvider data_readable_http_methods
     723     * @ticket 47620
     724     * @ticket 56481
     725     *
     726     * @param string $method HTTP method to use.
    646727     */
    647728    public function test_prepare_item() {
Note: See TracChangeset for help on using the changeset viewer.