B A C K
How to Override a REST Resource from Drupal Core

How to Override a REST Resource from Drupal Core

Knowledge Centre

Sometimes projects require us to find innovative solutions. Recently, we needed to override a core REST resource in Drupal 8, and given the limited documentation available, we decided to share our solution.

The Premises of a Drupal 8 Override

Drupal 8 handles configuration in a unified way, with more features stored in core than in previous versions. This architectural choice means that overriding core functionality requires careful consideration to avoid system damage.

While Drupal 8 supports global `$config` overrides through `Drupal\Core\Config\ConfigFactory::get()`, REST resource overrides require a different approach. Drupal 8's core provides basic REST resources for system entities, but complex operations often require extending these base classes.

Step-by-Step Guide to Override a REST Resource

1. Create a New Class

First, create a class that extends the `EntityResource` class:

  • namespace Drupal\my_module\Plugin\rest\resource;
  • use Drupal\rest\Plugin\ResourceBase;
  • use Drupal\rest\ResourceResponse;
  • use Drupal\node\Entity\Node;
  • /**
  • * @RestResource(
  • * id = "my_custom_node_rest_resource",
  • * label = @Translation("Custom Node REST Resource"),
  • * uri_paths = {
  • * "canonical" = "/api/v1/node/{node}",
  • * "create" = "/api/v1/node"
  • * }
  • * )
  • */
  • class MyCustomNodeResource extends EntityResource {
  • ....
  • }

2. Implement Required Methods

Override the necessary methods from the parent class:

  • /**
  • * Responds to POST requests.
  • *
  • * @param array $data
  • * The request data.
  • *
  • * @return \Drupal\rest\ResourceResponse
  • * The response containing the node.
  • */
  • public function post($data) {
  • // Your custom POST logic here
  • $response = new ResourceResponse($result, 201);
  • return $response;
  • }
  • /**
  • * Responds to PATCH requests.
  • *
  • * @param \Drupal\Core\Entity\EntityInterface $entity
  • * The entity.
  • * @param array $data
  • * The request data.
  • *
  • * @return \Drupal\rest\ResourceResponse
  • * The response.
  • */
  • public function patch($entity, array $data) {
  • // Your custom PATCH logic here
  • return new ResourceResponse($entity, 200);
  • }

3. Configure REST Resource Settings

Add the following to your module's configuration:

  • # config/install/rest.resource.my_custom_node_rest_resource.yml
  • langcode: en
  • status: true
  • dependencies:
  • module:
  • - my_module
  • - serialization
  • id: my_custom_node_rest_resource
  • plugin_id: my_custom_node_rest_resource
  • granularity: resource
  • configuration:
  • methods:
  • - GET
  • - POST
  • - PATCH
  • formats:
  • - json
  • authentication:
  • - basic_auth

4. Implement Access Controls

Add proper access checking:

  • /**
  • * {@inheritdoc}
  • */
  • public function access($operation, array $args = []) {
  • $entity = isset($args['entity']) ? $args['entity'] : NULL;
  • switch ($operation) {
  • case 'create':
  • return $this->checkCreateAccess();
  • case 'update':
  • return $this->checkUpdateAccess($entity);
  • default:
  • return parent::access($operation, $args);
  • }
  • }
  • ```
  • ### 5. Handle Exceptions
  • Implement proper error handling:
  • ```php
  • protected function handleException(\Exception $e) {
  • watchdog_exception('my_module', $e);
  • return new ResourceResponse([
  • 'error' => [
  • 'message' => $this->t('An error occurred while processing the request.'),
  • 'code' => 500,
  • ],
  • ], 500);
  • }

Best Practices

Always maintain backward compatibility when possible

Document your custom endpoints thoroughly

Implement proper access controls

Add comprehensive error handling

Use dependency injection instead of static service calls

Add proper request validation

Include appropriate response headers

Testing Your Custom Resource

Add PHPUnit tests to ensure your resource works as expected:

  • namespace Drupal\Tests\my_module\Functional;
  • use Drupal\Tests\rest\Functional\ResourceTestBase;
  • class MyCustomNodeResourceTest extends ResourceTestBase {
  • // Test implementation
  • }
  • Common Pitfalls to Avoid

Not handling all HTTP methods properly

Forgetting to update REST configuration after changes

Inadequate error handling

Missing access controls

Not validating input data

Improper response formatting

By following these steps and best practices, you can successfully override Drupal 8 core REST resources while maintaining system stability and security.