Make WordPress Core


Ignore:
Timestamp:
09/17/2024 09:50:38 PM (2 years ago)
Author:
TimothyBlynJacobs
Message:

REST API: Automatically populate targetHints for the Allow header.

The REST API uses the "Allow" header to communicate what methods a user is authorized to perform on a resource. This works great when operating on a single item route, but can break down when needing to determine authorization over a collection of items.

This commit uses the "targetHints" property of JSON Hyper Schema to provide access to the "allow" header for "self" links. This alleviates needing to make a separate network request for each item in a collection.

Props mamaduka, noisysocks, peterwilsoncc, spacedmonkey, swissspidy, timothyblynjacobs, tyxla, youknowriad.
Fixes #61739.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rest-api/class-wp-rest-server.php

    r58688 r59032  
    637637                                $attributes         = $item['attributes'];
    638638                                $attributes['href'] = $item['href'];
    639                                 $data[ $rel ][]     = $attributes;
     639
     640                                if ( 'self' !== $rel ) {
     641                                        $data[ $rel ][] = $attributes;
     642                                        continue;
     643                                }
     644
     645                                $target_hints = self::get_target_hints_for_link( $attributes );
     646                                if ( $target_hints ) {
     647                                        $attributes['targetHints'] = $target_hints;
     648                                }
     649
     650                                $data[ $rel ][] = $attributes;
    640651                        }
    641652                }
    642653
    643654                return $data;
     655        }
     656
     657        /**
     658         * Gets the target links for a REST API Link.
     659         *
     660         * @since 6.7.0
     661         *
     662         * @param array $link
     663         *
     664         * @return array|null
     665         */
     666        protected static function get_target_hints_for_link( $link ) {
     667                // Prefer targetHints that were specifically designated by the developer.
     668                if ( isset( $link['targetHints']['allow'] ) ) {
     669                        return null;
     670                }
     671
     672                $request = WP_REST_Request::from_url( $link['href'] );
     673                if ( ! $request ) {
     674                        return null;
     675                }
     676
     677                $server = rest_get_server();
     678                $match  = $server->match_request_to_handler( $request );
     679
     680                if ( is_wp_error( $match ) ) {
     681                        return null;
     682                }
     683
     684                if ( is_wp_error( $request->has_valid_params() ) ) {
     685                        return null;
     686                }
     687
     688                if ( is_wp_error( $request->sanitize_params() ) ) {
     689                        return null;
     690                }
     691
     692                $target_hints = array();
     693
     694                $response = new WP_REST_Response();
     695                $response->set_matched_route( $match[0] );
     696                $response->set_matched_handler( $match[1] );
     697                $headers = rest_send_allow_header( $response, $server, $request )->get_headers();
     698
     699                foreach ( $headers as $name => $value ) {
     700                        $name = WP_REST_Request::canonicalize_header_name( $name );
     701
     702                        $target_hints[ $name ] = array_map( 'trim', explode( ',', $value ) );
     703                }
     704
     705                return $target_hints;
    644706        }
    645707
Note: See TracChangeset for help on using the changeset viewer.