How to Override a REST Resource from Drupal Core
How to Override a REST Resource from Drupal Core
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_auth4. 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.
 
