0

I am preparing a plugin for REST API integration (the WP 4.7 core version) by providing custom endpoints for data from the plugin. One of the things I am trying to do is to set a _links property in the response and make the linked resource embeddable. Heavily simplified code excerpt:

class Clgs_REST_Logs extends WP_REST_Controller {
    const NSPACE = 'clgs';
    const BASE = 'logs';

    public function register_routes() {
        register_rest_route( self::NSPACE, '/' . self::BASE, array(
            array(
                'methods'   => WP_REST_Server::READABLE,
                'callback'  => array( $this, 'get_items' ),
             ),
            'schema' => array( $this, 'get_public_item_schema' ),
        ) );
        register_rest_route( self::NSPACE, '/' . self::BASE . '/count', array(
            array(
                'methods'   => WP_REST_Server::READABLE,
                'callback'  => array( $this, 'get_count' ),
            ),
            'schema' => array( $this, 'get_count_schema' ),
        ) );
    }

    public function get_items( $request ) {
        $log_entries = // get an array

        $collection = $this->prepare_collection_for_response( $log_entries, $request );
        $response = rest_ensure_response( array(
            'items' => $collection
         ) );

        $max_pages = max( 1, ceil( $total_items / (int) $params['per_page'] ) );

        $this->set_count_headers( $response, (int) $total_items, (int) $max_pages );

        $count_link =  $this->prepare_link_url( array( self::BASE, 'count' ) );
        $response->add_links( array (
            'count'  => array(
                'href' => $count_link,
                'embeddable' => true
            ),
        ) );

        return $response;
    }

    public function get_count( $request ) {
        // provide some statistics data
    }

    public function prepare_link_url ( $parts = array() ) {
        array_unshift( $parts, self::NSPACE );
        return rest_url( implode( '/', $parts ) . '/' );
    }
}

A response to a request http://wptesting.intern/index.php/wp-json/clgs/logs/?_embed looks like this:

{
    "items": [...],
    "_links": {
        "count": [{
            "embeddable": true,
            "href": "http://wptesting.intern/index.php/wp-json/clgs/logs/"
        }]
    },
    "_embedded": {
        "count": [{
            "code": "rest_no_route",
            "message": "No route was found matching the URL and request method",
            "data": {"status":404}
        }]
    }
}

Requests to http://wptesting.intern/index.php/wp-json/clgs/logs/count/, if done separately, succeeds.

I have done this additionally with pretty premalinks disabled and http://wptesting.intern/index.php/?route=... to be sure this is not a routing rewrite issue, and the same thing happens.

Has anyone an idea why the embedding fails?

0

The slash at the end is the culprit. While real requests with a / at the end of the route get wp_unslash()ed before resolving, the links for embeds do not.

So,

    public function prepare_link_url ( $parts = array() ) {
        array_unshift( $parts, self::NSPACE );
        return rest_url( implode( '/', $parts ) );
    }

does the trick.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.