Part 1 | Part 2 | Part 3

Decoupled Drupal has been a hot topic in the Drupal community for several years now, and there are now many projects implementing decoupled Drupal architectures, as well as a bevy of content (including my own articles on the subject). Nowadays, decoupled Drupal practitioners can now benefit from the first-ever comprehensive book about decoupled Drupal as well as a yearly decoupled Drupal conference. Presently, especially with the JSON:API module now available as part of Drupal core, getting started with decoupled Drupal has never been more accessible to more developers.

Nevertheless, there are still hidden areas of decoupled Drupal that have seldom seen much attention in the Drupal community for a variety of reasons. Some of these contributed Drupal modules have been around for quite some time and can help to shorten the amount of time you spend implementing a decoupled Drupal architecture, whether it comes down to a differing API specification or extending existing functionality.

Recently, your correspondent (Preston So, Editor in Chief at Tag1 Consulting and author of Decoupled Drupal in Practice) delivered a DrupalCon Seattle session about some of these lesser-known parts of the decoupled Drupal ecosystem. In this multi-part blog series, we embark on a tour through some of these exciting areas and dive into how these projects can accelerate your builds. In this second installment, we cover how you can leverage the RELAXed Web Services module for own purposes and how you can extend existing features in the JSON:API module now incorporated into core.

Working with RELAXed Web Services

Before we proceed, be sure to read the first installment in this series for a quick introduction to decoupled Drupal and a taxonomy of the architecture involved. The first installment in this blog series also introduces RELAXed Web Services and how to install and configure the module. From this point forward, it is presupposed that you have a working Drupal 8 site with RELAXed Web Services installed and configured.

To verify that RELAXed Web Services is working properly, we can issue the following GET request against the /relaxed endpoint (or whatever we have configured the URL in the previous installment of this blog series). The Drupal server should respond with a 200 response code and the following response body:

    {
      "couchdb": "Welcome",
      "uuid": "02286a1b231b68d89624d281cdfc0404",
      "vendor": {
        "name": "Drupal",
        "version": "8.5.6",
      },
      "version": "8.5.6"
    }

Retrieving data with RELAXed Web Services

The following table describes all of the GET requests that you can issue against a variety of resources provided by RELAXed Web Services.

RELAXed Web Services response

URI Description Example GET /relaxed/_all_dbs Retrieve all workspaces /relaxed/_all_dbs GET /relaxed/{workspace} Retrieve a single workspace /relaxed/live

/relaxed/stage GET /relaxed/{workspace}/_all_docs Retrieve all document identifiers (entity ids) in a workspace /relaxed/live/_all_docs GET /relaxed/{workspace}/{document_id} Retrieve a single document (Drupal entity) /relaxed/live/462e86f6-0123-43a6-a71e-914d9432ab6e

-->

The screenshot below demonstrates a sample RELAXed Web Services response to a GET request targeted to retrieve a single Drupal entity.

RELAXed Web Services response

Creating entities with RELAXed Web Services

To create documents, which in RELAXed Web Services parlance are equivalent to Drupal entities, you can issue a POST request to the /relaxed/live endpoint (or prefixed with the custom API root you have configured) with the following request body. The server will respond with a 201 Created response code.


    {
      "@context": {
        "_id": "@id",
        "@language": "en"
      },
      "@type": "node",
        "_id": "b6cea743-ba86-49b0-81ac-03ec728f91c4",
        "en": {
          "@context": {
            "@language": "en"
          },
        "langcode": [{ "value": "en" }],
        "type": [{ "target_id": "article" }],
        "title": [{ "value": "REST and RELAXation" }],
        "body": [
          {
            "value": "This article brought to you by a request to RELAXed Web
    Services!"
          }
        ]
      }
    }

Because a full description of RELAXed Web Services is well beyond the scope of this survey blog series, this section provided just a taste of some of the ways in which RELAXed Web Services differs from some of the other API approaches available in the decoupled Drupal ecosystem, including Drupal 8's native core REST and HAL (Hypertext Application Language).

Nonetheless, for developers looking for RESTful solutions that are more flexible than core REST and better-suited to offline solutions than JSON:API in many cases, RELAXed Web Services provides a powerful RESTful alternative. For more information about RELAXed Web Services and information about modifying and deleting individual documents remotely in Drupal, please consult Chapters 8 and 13 of my book Decoupled Drupal in Practice.

Extending JSON:API with Extras and Defaults

Oftentimes, when using modules like JSON:API, which is now available as part of Drupal 8 core for developers to leverage, we need to override the preconfigured defaults that accompany the module upon installation. Luckily, there are two modules available in Drupal's contributed ecosystem that can make this process much easier, especially given the fact that JSON:API aims to work out of the box as a zero-configuration module.

JSON:API Extras

The JSON:API Extras module provides interfaces to override default settings and configure new ones that the resulting API should follow in lieu of what comes off the shelf in the JSON:API module. Some of the features contained in the module include capabilities such as enabling and disabling individual resources from the API altogether, aliasing resource names and paths, disabling individual fields within entity responses, aliasing constituent field names, and modifying field output through field enhancers in Drupal.

You can install both modules easily with Composer. JSON:API Defaults, which we cover later in this section, is available as a submodule of JSON:API Extras.

    # Install JSON:API Extras.
    $ composer require drupal/jsonapi_extras
    $ drush en -y jsonapi_extras

    # Install JSON:API Defaults.
    $ drush en -y jsonapi_extras jsonapi_defaults

In the following image, you can see how we can override certain preconfigured settings in JSON:API such as disabling the resource altogether, changing the name of the resource type, and overriding the resource path that follows the /jsonapi prefix.

Add JSON:API resource

In the image below, field customization is displayed in JSON:API Extras, a feature that allows you to alias fields and perform other actions that permit you to customize the response output in a more granular way. As you can see, one of the most compelling motivations for JSON:API Extras on your own implementation is the notion of full customization of JSON:API's output not only at the resource level but at the field level as well.

Field customization

JSON:API Defaults

Formerly an entirely separate module maintained by Martin Kolar (mkolar), JSON:API Defaults allows you to set default includes and filters for resources in JSON:API. JSON:API Defaults is particularly useful when consumers prefer issuing slimmer requests without the parameters required to yield a response that includes relationships in the payload. In other words, you can issue a request without parameters and receive a response having predetermined defaults such as includes.

Though a full discussion of JSON:API Defaults is outside the scope of this rapid-fire survey of the lesser-known parts of the decoupled Drupal ecosystem, I highly encourage you to check out Chapter 23 in my book Decoupled Drupal in Practice, which engages in an in-depth discussion of JSON:API Extras and JSON:API Defaults.

Running Drupal remotely

Sometimes, merely interacting with Drupal content through APIs in decoupled Drupal is insufficient for the use cases and requirements that our customers demand. Deeper functionality in Drupal is often required remotely for consumer applications to access, particularly actions such as performing a cache registry rebuild or running a cron job. But these do not necessarily fit neatly into the normal API-driven approaches for Drupal entities, because they are not part of the RESTful paradigms in which Drupal generally operates out of the box.

In decoupled Drupal and other software ecosystems, remote procedure calls (RPCs) are calls that execute a procedure on another system, written as if they were local actions, without direct code written against that other system. In short, in the decoupled Drupal context, they are a convenient way for consumer applications to perform tasks remotely without their developers needing to understand the nuts and bolts of the upstream system. In the next installment of this blog series, we'll cover Drupal's RPC approach for decoupled Drupal and how you can leverage it for a variety of tasks you need in your client.

Conclusion

In this blog post, we surveyed several of the major API-first solutions available for decoupled Drupal aficionados that have not received as much attention as of late, including RELAXed Web Services and supplementary modules that provide additional features like JSON:API Extras and JSON:API Defaults. Over the course of this post, we covered how to retrieve entities using RELAXed Web Services and how you can customize your JSON:API resources and fields to your heart's content.

In the following installment of this multi-part blog series, we dive into JSON-RPC, the RPC provider for decoupled Drupal and discuss how to perform certain tasks using the JSON-RPC module. In addition, we'll cover derived schemas and API documentation, two of the most important concepts in the emerging API-first landscape that is beginning to gain significant attention in the headless CMS community.

Special thanks to Michael Meyers for his feedback during the writing process.

Part 1 | Part 2 | Part 3


For more on decoupled Drupal, see our Decoupled Drupal page.


Photo by Stefan Steinbauer on Unsplash