Drupal 8 - REST/JSON integration

Drupal 8 REST/JSON - integration with JavaScript application

Over the course of recent years, websites have undergone a significant change. Many new services and social media websites have been created. Mobile applications now play a very significant role on the internet, and various on-line services exchanging data is nothing out of the ordinary anymore. We could even say that integration with external services is standard now, especially in the case of large e-commerce applications or on-line payment systems.
Here we may ask ourselves a question: can we communicate with external services using Drupal? Of course we can! Being a drupal agency, as part of drupal development work for our clients, we have to integrate with various javascript applications.

In this post, we will how do do this in Drupal 8. We are going to discuss one of the more popular data exchange formats - JSON.

In our example, we are going to use Drupal 8.2^ and jQuery to write a simple JavaScript application. We are going to use Drupal as our CMS for managing data, and our content will be displayed on a “light” HTML website.


1. First, we install Drupal 8 and turn on our modules:

  • The RESTful Web Services API is new in Drupal 8
  • Serialization

chosen services being ticked


2. Then we download and turn on the REST UI module (this step is optional but useful).

https://www.drupal.org/project/restui
This module enables the user to manage access and data format via the UI (administration panel). It works with Drupal 8.2 or newer.


3. Configuration using REST UI - displaying the node in JSON format.


Now we are going to adapt our content type to integration. In our example, we are going to use the NODE entity. Go to /admin/config/services/rest. Select “content type” and set format json, auth cookie in the GET method. In this case, we are only going to download data, so the GET method will be perfectly fine.

Drupal 8 rest UI


If you decide not to install the REST UI module, you will have to enter the settings for all entities manually in config files. The above settings look as follows:
Filename:  rest.resource.entity.node.yml

uuid: add2fdec-b11f-45ad-a74f-3d30e36ad72f
langcode: en
status: true
dependencies:
  module:
    - node
    - serialization
    - user
id: entity.node
plugin_id: 'entity:node'
granularity: method
configuration:
  GET:
    supported_formats:
      - json
    supported_auth:
      - cookie


4. Let’s now create our node.


Assuming that our new node is located at http://www.drupal8.dev/node/1
we have to add a ?_format=json parameter, which gives us the following address: domain.example/node/1?_format=json 


If everything is configured properly, we should now have a node object in JSON format. If you display JSON content in your browser, you can install an add-on or extension for formatting JSON code (the one you can see on the screenshot is JSON Lite https://addons.mozilla.org/en-US/firefox/addon/json-lite/?src=api)

drupal node in JSON format


5. List of nodes in JSON


All right, so downloading single nodes is already working. Let’s now try to get a list of nodes.
We are going to use the Views module.

views - creating json


Provided that we are not going to use the majority of available data, we can select just the fields that concern us in order to reduce the amount of data transferred.

JSON rest options in views

To sum up: we created a list of content located at /node_list, and by adding ?=_format=json to our URL we can download any of them in JSON format.


6. Own address for REST/JSON (endpoint)


If - for any reason - the above solutions aren’t enough, we can create our own endpoint and add new data to our JSON.
Let’s create routing and a controller.


Routing


First, let’s start from creating a routing at, e.g. /v1/custom_endpoint. Entering our API version in the URL is definitely good practice since while creating a newer version we can leave it at /v2/custom_endpoint, /v3/... etc. This way our users who use an older version of the API won’t get cut off from our resources.
Routing example:

ev_client_endpoint:
  path: '/v1/custom_endpoint'
  methods:  [GET]
  defaults:
    _controller: 'Drupal\ev_client_endpoint\Controller\EvEndpoint::get'
  requirements:
    _permission: 'access content'


Explanation: by requesting GET at /v1/custom_endpoint we are going to receive the data returned by EvEndpoint controller executing GET method.


Controller


For this example, we will assume that our endpoint is supposed to return basic information about our website - the name and e-mail address, current timestamp and a random node with ID of 1 through 10.

<?php

namespace Drupal\ev_client_endpoint\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\node\Entity\Node;
use Symfony\Component\HttpFoundation\JsonResponse;

/**
 * An example controller.
 */
class EvEndpoint extends ControllerBase {

  /**
   * {@inheritdoc}
   */
  public function get() {

    $response = new JsonResponse();
    $config = \Drupal::config('system.site');
    $node = Node::load(random_int(1,10));
    $data = array(
      'date' => time(),
      'site_name' => $config->get('name'),
      'site_email' => $config->get('mail'),
      'random_node' => array(
        'title' => $node->get('title')->getValue()[0]['value'],
        'body' => $node->get('body')->getValue()[0]['value'],
      )
    );

    $response->setData($data);

    return $response;

  }
}


After doing everything correctly, we can clean our cache and go to /v1/custom_endpoint. The end result should be as follows.

​
{
"date": 1481920261,
"site_name": "custom endpoint site",
"site_email": "admin@examplesite",
"random_node": {
"title": "title node 5",
"body": "body node 5"
}
}

​


7. Receiving JSON


Let’s now create a simple JavaScript to display our data on the website.
If we are going to connect from domains other than our Drupal, the https://www.drupal.org/project/cors, adding headers to requests or creating a virtual proxy might be useful, so that all the requests are seen as local (you can find out more at https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS)


Code html index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src="app.js"></script>
</head>
<body>

</body>
</html>


Now we can add our app.js file and jQuery library in the Head section.
Script app.js

$(document).ready(function () {
  $.ajax({
    type: 'GET',
    url: 'http://drupal8.dev/v1/custom_endpoint',
    success: function (data) {
      {
        var date = new Date(data.date * 1000);
        $('body').append('' +
          '<h1 class="name">' + data.random_node.title + '</h1>' +
          '<content class="body">' + data.random_node.body + '</content>' +
          '<email class="mail">' + data.site_email + '</email>' +
          '<div class="date">' + date  + '</div>' +
          '<h2 class="email">' + data.site_name + '</h2>'
        );
      }
    }
  });
});


Download JSON from our Drupal: /v1/custom_endpoint


The data variable contains our json, now we can add it with our variables to the HTML body using append function.


If everything has been done properly, upon displaying index.html in our browser, the JavaScript requests the data from our Drupal and downloads it in JSON format, and then adds them to the body of our website.


Summary

These are some basic information regarding starting the adventure with web services using Drupal. In the next part, we are going to write about logging into Drupal using an existing user account, as well as adding and editing content via REST/JSON.
If you want to further expand your knowledge about D8 and other tools useful for designing web applications, give us a like on Facebook, where we share our tutorials, guides and various interesting stuff from the industry. You can also take part in DrupalDay and the DrupalCamp! New content is also coming soon to our blog!

3. Best practices for software development teams