Custom REST Resources

Last updated on
29 March 2024

This page has not yet been reviewed by RESTful Web Services API maintainer(s) and added to the menu.

Setting Up the Module

First, setup a new custom Drupal module – See Creating Custom Modules more detail instructions on how to do this.

Let’s create a module name Demo REST API. To do so, create a new directory in/modules/custom/ named demo_rest_api and add an info file for the module.

Example: demo_rest_api.info.yml

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

Once that is all in place, you should be able to enable your new module in the Drupal Admin.

Creating the Resource Plugins

In order to create a custom REST service, you will need to become acquainted with Plugins. Plugins are small pieces of functionality that are swappable. Plugins that perform similar functionality are of the same plugin type. In the case of our custom resource, we need to extend the ResourceBase plugin, which can be found here

In order to implement a ResourceBase plugin in our REST module, create a new fileDemoResource.php in /src/Plugin/rest/resource/ directory of the Demo REST API module and add the following:

<?php

namespace Drupal\demo_rest_api\Plugin\rest\resource;

use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;

class DemoResource extends ResourceBase {

}

To review the above, we are setting the namespace for our PHP class and then using theResourceBase class which we will be extending. We are also using theResourceResponse class which will be used to send the response. 

In order to configure our endpoint we will be utilizing Plugin annotations. Specifically, the Plugin implementation must be annotated with the @RestResource annotation so that it can be discovered. Doing so will also allow you to set the Plugin id, label, and endpoint urls. A complete annotation will look like this:

/**
 * Provides a Demo Resource
 *
 * @RestResource(
 *   id = "demo_resource",
 *   label = @Translation("Demo Resource"),
 *   uri_paths = {
 *     "canonical" = "/demo_rest_api/demo_resource"
 *   }
 * )
 */
class DemoResource extends ResourceBase {

}

At this point the resource is now defined, and discoverable but it doesn’t actually do anything. To handle GET requests, implement a static get method on Demo Resourceand return an instance of ResourceResponse

/**
 * Provides a Demo Resource
 *
 * @RestResource(
 *   id = "demo_resource",
 *   label = @Translation("Demo Resource"),
 *   uri_paths = {
 *     "canonical" = "/demo_rest_api/demo_resource"
 *   }
 * )
 */
class DemoResource extends ResourceBase {

  /**
   * Responds to entity GET requests.
   * @return \Drupal\rest\ResourceResponse
   */
  public function get() {
    $response = ['message' => 'Hello, this is a rest service'];
    return new ResourceResponse($response);
  }
}

Route parameters

The paths defined in the plugin's annotation can use placeholders the same way that routes do, whose values will be passed to the get() method if it has parameters whose names match the placeholders.

The request, route, and route match objects can also be passed to the get() method by typehinting them, the same way as controller callbacks.

Configuration

If you are using the REST UI contrib module, you should now be able to see it in the list of available endpoints and you should be able to configure the GET method.

You can also manually import the configuration – See REST Web Services overview for detailed instructions on how to configure REST services.

Example REST resource config (<MODULE_NAME>/config/install/rest.resource.demo_resource_config.yml):

id: demo_resource_config
plugin_id: demo_resource
granularity: method
configuration:
  GET:
    supported_formats:
      - json
    supported_auth:
      - basic_auth

This config file name needs to follow the convention of rest.resource.<my_id_string>.yml and the id: in the config file must match <my_id_string>

To add additional configuration information, you can use the settings.yml in config/optional like ./modules/rest/config/optional/rest.resource.entity.node.yml. In our case, it would be /modules/custom/demo_rest_api/config/optional/rest.resource.demo_resource.yml.

You should now be able to send a GET request to /demo_rest_api/demo_resource?_format=json with Content-Type header set to application/json andAuthorization header set to your drupal user name and password and receive the following response:

{
  "message": "Hello, this is a rest service"
}

POST Requests

To allow POST method usage, see https://www.drupal.org/docs/drupal-apis/restful-web-services-api/restful... . Note, in particular, the addition of the create uri_path in the annotation.

This post is part 1 in the 3 part series. Parts 2 & 3 will be coming soon.

Note : Custom REST Resources are not being discovered while naming module in camel casing last tested in Drupal version 8.5.6 (Similar to custom blocks are not being discovered while naming module in camel casing).

Help improve this page

Page status: No known problems

You can: