Custom Rest API - Part 2

In the previous part-1 of this series we talked about the Rest API and how can we define the Rest API Plugin type in your system. In the previous example we have defined the REST Plugin in your custom module, add some get()/Post() methods for reading and writing operations. 

Now in this series of Rest API or Rest API part-2, we will discuss more about REST API and we will show how to define REST API using a custom controller class.
Now the question arises here why do we need this custom Rest API controller class over the REST API plugins?

We will discuss the answer to the above question through these differences as mentioned below in the table:

REST Resouce Plugin Rest Controller Endpoints

Need to define the REST API endpoints URLs in a plugins class, means there is no routing file

Need to define endpoints in routing files.
You can set only limited or 1 permissions You can set an unlimited number of permissions or custom permission as well.
Once the endpoints are defined you need to enable them using the Drupal console or REST UI. There is no need to enable the URL endpoints. Once the custom class enables the endpoints URLs are automatically enabled.
For every endpoint, need to define new REST Resource plugins One class can be used for many endpoints.
Extra parameter need to be passed with the Endpoints URLs like
/example/test?_form=Json or 
/example/test?_form=hal+Json 
There is no need for passing extra parameters in endpoints URLs. 

 

Define Custom Rest Controller endpoints

We can define our custom REST Endpoints as we define our custom normal controller class. So our first step is to create a custom module and define the info.yml file in modules->custom->custom_rest_endpoints. Here our custom module name is custom_rest_endpoints and our info file name will be custom_rest_endpoints.info.yml. Now define the module-info in this file like:

The custom module-info

name:  Custom REST Endpoints
description: Define's a custom REST Resource.
package: Custom
type: module
core: 8.x 

The custom Routes
Now after defining the module-info file, we need to define routes for our custom rest, which will serve as endpoints for the application.

custom_rest_endpoints.get_node:
  path: 'api/custom/endpoint/getnode'
  defaults:
    _controller: '\Drupal\custom_rest_endpoints\Controller\CustomRestEndpointsController::getNode'
  methods: [GET]
  requirements:
    _permission: 'access custom endpoint'

Here we have defined custom permission "access custom rest endpoints". If we want to available this endpoint to the public  the simply changes it to 

_access: 'TRUE'

Or if we want to add multiple permissions to this endpoint then 

_permission: 'access custom endpoint, view custom content'

The custom Permission
Defining our custom permission is straight forward way as we define it in our Drupal like defining our custom permission in custom_rest_endpoints.permission.yml file

access custom endpoint:
  title: 'Allow access to custom REST endpoints'

The custom Controller
Now define a custom controller base class in src->Controller->CustomRestController.php, that will server response data when our endpoints call. It is the same as we define in Drupal 8/9 and so on.

<?php

namespace Drupal\custom_rest_endpoints\Controller;

use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\HttpFoundation\JsonResponse;
use Drupal\node\Entity\Node;

/**
* Class CustomRestController.
*/
class CustomRestController extends ControllerBase {

 /**
   * Return the 10 most recently updated nodes in a formatted JSON response.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   *   The formatted JSON response.
   */
  public function getNode() {
    // Initialize the response array.
    $response = [];

    // Load the 10 most recently updated nodes and build an array of titles
    // to be returned in the JSON response.
    $nodes = \Drupal::entityQuery('node')
    // Published or not.
      ->condition('status', 1)
      ->sort('changed', 'DESC')
      ->range(0, 10)
      ->execute();

    if ($nodes) {
      foreach ($nodes as $node) {
        $node = Node::load($node);
        $response[] = [
          'title' => $node->getTitle(),
        ];
      }
    }
    else {
      // Set the default response to be returned if no results can be found.
      $response = ['message' => 'No new nodes.'];
    }

    // Create the JSON response object and add the cache metadata.
    $responsedata = new JsonResponse($response);

    return $responsedata;
  }

}

The Testing of our endpoint