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/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php

    r59801 r59899  
    412412        $args['post_type'] = $this->post_type;
    413413
     414        $is_head_request = $request->is_method( 'HEAD' );
     415        if ( $is_head_request ) {
     416            // Force the 'fields' argument. For HEAD requests, only post IDs are required to calculate pagination.
     417            $args['fields'] = 'ids';
     418            // Disable priming post meta for HEAD requests to improve performance.
     419            $args['update_post_term_cache'] = false;
     420            $args['update_post_meta_cache'] = false;
     421        }
     422
    414423        /**
    415424         * Filters WP_Query arguments when querying posts via the REST API.
     
    444453        }
    445454
    446         $posts = array();
    447 
    448         update_post_author_caches( $query_result );
    449         update_post_parent_caches( $query_result );
    450 
    451         if ( post_type_supports( $this->post_type, 'thumbnail' ) ) {
    452             update_post_thumbnail_cache( $posts_query );
    453         }
    454 
    455         foreach ( $query_result as $post ) {
    456             if ( ! $this->check_read_permission( $post ) ) {
    457                 continue;
    458             }
    459 
    460             $data    = $this->prepare_item_for_response( $post, $request );
    461             $posts[] = $this->prepare_response_for_collection( $data );
     455        if ( ! $is_head_request ) {
     456            $posts = array();
     457
     458            update_post_author_caches( $query_result );
     459            update_post_parent_caches( $query_result );
     460
     461            if ( post_type_supports( $this->post_type, 'thumbnail' ) ) {
     462                update_post_thumbnail_cache( $posts_query );
     463            }
     464
     465            foreach ( $query_result as $post ) {
     466                if ( ! $this->check_read_permission( $post ) ) {
     467                    continue;
     468                }
     469
     470                $data    = $this->prepare_item_for_response( $post, $request );
     471                $posts[] = $this->prepare_response_for_collection( $data );
     472            }
    462473        }
    463474
     
    489500        }
    490501
    491         $response = rest_ensure_response( $posts );
     502        $response = $is_head_request ? new WP_REST_Response() : rest_ensure_response( $posts );
    492503
    493504        $response->header( 'X-WP-Total', (int) $total_posts );
     
    18331844
    18341845        setup_postdata( $post );
     1846
     1847        // Don't prepare the response body for HEAD requests.
     1848        if ( $request->is_method( 'HEAD' ) ) {
     1849            /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php */
     1850            return apply_filters( "rest_prepare_{$this->post_type}", new WP_REST_Response(), $post, $request );
     1851        }
    18351852
    18361853        $fields = $this->get_fields_for_response( $request );
Note: See TracChangeset for help on using the changeset viewer.