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
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.
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)
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.
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.
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!