Web services

by Gisle Hannemyr

Mumble

Table of contents

Introduction

Guzzle

Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and trivial to integrate with web services. Features:

Documentation:

Installing Guzzle

To install Guzzle using composer, put the following composer.json in the module that will need Guzzle:

{
    "require": {
        "guzzlehttp/guzzle": "^6.3"
    }
}

When you later enable the module with drush, all dependencies will be sorted out.

Using

For a Drupal module to be able to use Guzzle it needs the following two lines:

require_once 'sites/all/vendor/autoload.php';
use GuzzleHttp\Client;

Then the following may be used.

$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle');
echo $res->getStatusCode();
// 200
echo $res->getHeaderLine('content-type');
// 'application/json; charset=utf8'
echo $res->getBody();
// '{"id": 1420053, "name": "guzzle", ...}'

// Send an asynchronous request.
$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org');
$promise = $client->sendAsync($request)->then(function ($response) {
    echo 'I completed! ' . $response->getBody();
});
$promise->wait();

Here is an example of setting up basic authentication and checking the response.

$client = new GuzzleHttp\Client();
$res = $client->get('http://www.example.com/endpoint', [
    'auth' => [
        'username', 
        'password'
    ]
]);
$statuscode = $res->getStatusCode();
debug($statuscode, 'statuscode');

Provided all went well, the call to debug() will output “200”.

Services

The Services provides Drupal with a standardized solution for building API's so that external clients can communicate with Drupal. Out of the box it aims to support anything Drupal core supports. It provides a code level API (through sub-modules for REST and XMLRPC) for other modules to expose their features and functionality via HTTP or HTTPS. It provide Drupal plugins that allow others to create their own authentication mechanisms, request formats, and response formats.

This case study describes how to set up a RESTful Web Service (RWS), using leveraging on the contributed Services project. It will also discuss how to test it and finally describe how to build a native ToDo-app for Android to interact with this web service.

See alsoFor introductions to RWS, please see Alex Rodriguez: RESTful Web services. Basic principles of REST Web services and Zell Liew: Understanding And Using REST APIs. For more background information you may also want to read the Wikipedia article about Representational_state_transfer.

Install Drupal Services

Before you start familiarise yourself with these software resources and informatio sources:

  1. Services (Drupal project, version 7.x-3.24).
  2. Drupal Groups: Services
  3. Drupal modules using Services
  4. Spyc (PHP library).
  5. cURL (CLI tool to make HTTP-requests).
  6. RESTED (Firefox plugin, GitHub (documentation), Espen Henriksen (creator).

The documentation is extensive, but spread over several books and some of it is outdated. Here are links to the most relevant parts.

  1. Top level book.
  2. Services version 3.
  3. Testing Services with the node resource.
  4. Creating a resource for Services 3.x.

This chapter is based upon these writings.

The Services API is on the project's /docs folder:

  1. services.authentication.api.php – hooks related to authentication plugins
  2. services.servers.api.php – servers definition hooks
  3. services.services.api.php – definition of new services
  4. services.versions.api.php – how to write versioned resources

These variables may be set:

  1. services_{$resource}_index_page_size – this variable controls maximum number of results that will be displayed by index query. See services_resource_build_index_query() for more information.
  2. services_generate_error_body – boolean denoting whether a message body should be included with certain HTTP error-related status codes. (According to IETF's RFC2616, 204 and 304 responses must not include bodies.)

These steps are required to set up Services and make it ready for testing:

  1. Intall dependencies (CTools and Libraries).
  2. Install and enable Services.
  3. Install latest version of Spyc (library version 0.6.2). Rename from “Spyc.php” to “spyc.php” and install in directory “servers/rest_server/lib” under the project's root directory.
  4. Enable sub-module REST Server
  5. Install cURL for the CLI
  6. Install RESTED plugin for Firefox

The main Services controls are found if you navigate to Structure » Services.

To create a new service definition Click on the “Add” link. To import a service definition that has been exported from another Drupal website, use the “Import” link.

Services are defined as “endpoints”. An endpoint is a unique URL stem that acts as a base for all calls. Each endpoint is defined by a combination of URL, server, and authentication. So for instance you could define two REST services, one authenticated and one available for anonymous users, with unique URLS like:

In addition to defining a unique URL, the service definition specifies what type of server is used to return data requests (e.g., REST, XMLRPC, etc.):

services01.png
Setting up a new endpoint for a REST server.

After the service has been created, you can click the link in its “Edit Resources”-button in the “Operations”-column for the resource to define it further. Thos produces five tabs:

Pressing the small triangle to the right of the link expands a drop-down menu that links to the same items as the tabs described above, and three additional ones (Disable/enable, Delete, Clone).

Test Drupal Services

You can test whether Services is working by enabling a resource and retrieving that resource.

For this first test, disable all authentication. You can enable the authentication later after you have confirmed that the service you have created is returning results as expected.

For the purpose of this test, we will assume that you have created a REST service where the machine-readable name of the endpoint is “test_service” with the path to thepoint endpoint being “test”. When you edit your service it should look like this:

services02.png
Editing the test_service.

Using the node resource for testing is a good way to get started because creating nodes is easy in Drupal and because the Services module provides the full range of CRUD methods for nodes: create, retrieve, update, delete (and index).

Since you have not enabled authentication, Services has no way of associating your request with a user ID and will treat all requests as coming from an anonymous user. In order to retrieve node information, therefore, the “View published content” permission must be enabled for the anomymous user.

Yu must enable response formatters and request parsing under the Server tab. For this test, enable json and xml and application/json.

The URI for the resource is put together from the information configured under the “Edit” tab for the resource. Below is both the formula and an example of the URI to get node 6 from a web service installed on a site named “example.org” provided the path to the endpoint is “test”:

http[s]://your_domain/your_endpoint_path/your_resource_path.response_format
http://example.org/test/node/6.json
http://www.copymarks.org/test/node/6.json

Enable the resource that may be consumed under the Resources tab. You do this by putting a checkmark in the box to the left of the resource. For this test, enable “node”. Also enable the operations that will be allowed for the resource. For this test, enable all of them. When done, press “Save”.

If you only specify a single response formatter, it will be returned by default (and you can leave out the response format part of the URI). If you enable more than one, xml is the default (assuming that the web service has XML enabled). You may add the desired response format to the URI. You do this by adding a period followed by the abbreviation for that response format to the end of the URL. If the requested response format is not enabled, the server returns 406 (Unknown or unsupported response format).

The RESTful interface uses the following methods:

It takes a little more effort to put together POST, PUT and DELETE methods, so we'll start by testing some “retrieve” and “index” requests.

To retrieve the example node using cURL:

$ curl http://www.example.org/test/node/6.json
{
  "vid":"6",
  "uid":"1",
  "title":"Welcome!",
   …

Screendump of retrieving the sme node using the RESTED firefox plugin:

rested01.png
Screenshot showing the result of using the RESTED Firefox plugin to retrieve a node.

ToDo project

Create a Todo resource project that will contain our service implementation. The .info file could look something like this:

name = ToDo Resource
description = Sample resource implementation
core = 7.x
dependencies[] = services

Final word

[TBA]


Last update: .2019-04-21 [gh].

X