How to create Custom RESTful API in Drupal 8

Drupal 8 RESTful APIThis is a very simple module that demonstrates implementation of a custom RESTful API in Drupal 8. Creating your own API with Drupal 8 has become a routine task that doesn't require a lot of work. However there are a lot of things I am not covering in this blog post, such as user login and user registration etc...

You could also look into Rest module (in core) to see how to use it's plugin API to extend core rest functionality.

I use Postman to test my API endpoints (this is an app that allows you to send POST/GET/PUT/DELETE etc.. requests and see API response).

Test API module (test_api.module) contains the following files:

  • test_api.info.yml - Module .info file
  • test_api.module - Empty module file
  • test_api.routing.yml - Routing file with all the API paths:

    # Test API endpoints
    
    test_api.get:
      path: 'my-api/get.json'
      defaults: { _controller: '\Drupal\test_api\Controller\TestAPIController::get_example' }
      methods:  [GET]
      requirements:
        _access: 'TRUE'
    
    test_api.put:
      path: 'my-api/put.json'
      defaults: { _controller: '\Drupal\test_api\Controller\TestAPIController::put_example' }
      methods:  [PUT]
      requirements:
        _access: 'TRUE'
    
    test_api.post:
      path: 'my-api/post.json'
      defaults: { _controller: '\Drupal\test_api\Controller\TestAPIController::post_example' }
      methods:  [POST]
      requirements:
        _access: 'TRUE'
    
    test_api.delete:
      path: 'my-api/delete.json'
      defaults: { _controller: '\Drupal\test_api\Controller\TestAPIController::delete_example' }
      methods:  [DELETE]
      requirements:
        _access: 'TRUE'
    
  • src/Controller/TestAPIController.php - Main controller file:

    /**
     * @file
     * Contains \Drupal\test_api\Controller\TestAPIController.
     */
    
    namespace Drupal\test_api\Controller;
    
    use Drupal\Core\Controller\ControllerBase;
    
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\JsonResponse;
    
    /**
     * Controller routines for test_api routes.
     */
    class TestAPIController extends ControllerBase {
    
      /**
       * Callback for `my-api/get.json` API method.
       */
      public function get_example( Request $request ) {
    
        $response['data'] = 'Some test data to return';
        $response['method'] = 'GET';
    
        return new JsonResponse( $response );
      }
    
      /**
       * Callback for `my-api/put.json` API method.
       */
      public function put_example( Request $request ) {
    
        $response['data'] = 'Some test data to return';
        $response['method'] = 'PUT';
    
        return new JsonResponse( $response );
      }
    
      /**
       * Callback for `my-api/post.json` API method.
       */
      public function post_example( Request $request ) {
    
        // This condition checks the `Content-type` and makes sure to 
        // decode JSON string from the request body into array.
        if ( 0 === strpos( $request->headers->get( 'Content-Type' ), 'application/json' ) ) {
          $data = json_decode( $request->getContent(), TRUE );
          $request->request->replace( is_array( $data ) ? $data : [] );
        }
    
        $response['data'] = 'Some test data to return';
        $response['method'] = 'POST';
    
        return new JsonResponse( $response );
      }
    
      /**
       * Callback for `my-api/delete.json` API method.
       */
      public function delete_example( Request $request ) {
    
        $response['data'] = 'Some test data to return';
        $response['method'] = 'DELETE';
    
        return new JsonResponse( $response );
      }
    
    }
    

This is how you get headers from the $request object:

$request->headers->get( 'Content-Type' );

This is how you get request body from the $request object:

$request->getContent();

Download Test API from Github