Thông tin về HTTP với Drupal::httpClient

With the release of Drupal 8 comes a new way of making web requests, available via the Drupal::httpClient. This is simply a wrapper for the wonderful Guzzle HTTP Client. In this post, we'll take a look at how we can use the Drupal::httpClient class for making HTTP requests in a module. This is particularly useful when you wish to communicate with external websites or web services.

>> Phần 3 - Custom Image Search với Solr, Filefield Sources và Ctools

>> Phần 2 - Custom Image Search with Solr, Filefield Sources và Ctools

>> Phần 1 - Custom Image Search với Solr, Filefield Sources và Ctools

In Drupal 7, you would have used the drupal_http_request function for sending HTTP requests. This functionality now exists in Drupal::httpClient for Drupal 8.

Drupal and Guzzle (in short)

According to the Guzzle project page, "Guzzle is a PHP HTTP client and framework for building RESTful web service clients."

Guzzle utilizes PSR-7 as the HTTP message interface. PSR-7 describes common interfaces for representing HTTP messages. This allows Guzzle to work with any other library that utilizes PSR-7 message interfaces.

You can check the version of Guzzle that you’re using by taking a look at the composer.lock file in your Drupal project directory.

Drupal 8.0.1 comes with Guzzle 6.0.1:


  {
    "name": "guzzlehttp/guzzle",
    "version": "6.1.0",
    "source": {
      "type": "git",
      "url": "https://github.com/guzzle/guzzle.git",
      "reference": "66fd14b4d0b8f2389eaf37c5458608c7cb793a81"
    },
  // ...
  },

The Guzzle documentation is available here.

Drupal::httpClient in a module

Data.gov provides a catalog of data via CKAN, a powerful open source data platform that includes a robust API. We're going to take a look at some examples using the CKAN API, full documentation is available here.

First, let's take a quick look at how we make requests in Drupal. You can initialize a client like so:


  $client = \Drupal::httpClient();

When you initialize a client, you can pass a base_url parameter:


 $client = \Drupal::httpClient([
   'base_url' => 'http://demo.ckan.org'
 ]);
$client->request('GET', '/api/3/action/package_list');

Or simply pass the full URL in your request:


  $client->request('GET', 'http://demo.ckan.org/api/3/action/package_list')

Guzzle also provides a list of synchronous methods for making requests, a full list is available here:

You can make GET requests as follows:


  $client = new Client('http://demo.ckan.org');
  $request = $client->get('/api/3/action/package_list');
  $response = $request->getBody();

Next, let's POST some JSON to a remote API:


  $client = \Drupal::httpClient();
  $request = $client->post('http://demo.ckan.org/api/3/action/group_list', [
    'json' => [
      'id'=> 'data-explorer'
    ]
  ]);
  $response = json_decode($request->getBody());

In the client->post() method above, we pass in a URL string, and an array of request options. In this case, 'json', and an array of the properties we'd like to send as JSON. Guzzle takes care of adding a 'Content-Type','application/json' header, as well as json_encoding the 'json' array. We then call json_decode to decode the response of our request.

A full list of request options is available on the project's website: Guzzle Request Options.

Example: HTTP basic authentication

What about handling HTTP basic authentication with GitHub's API, for example?


  $client = new Client('https://api.github.com');
  $request = $client->get('/user', [
    'auth' => ['username','password']
  ]);
  $response = $request->getBody();

Exception handling

When using Drupal::httpClient, you should always wrap your requests in a try/catch block, to handle any exceptions. Here is an example of logging Drupal::httpClient request exceptions via watchdog_exception.


  $client = \Drupal::httpClient();

  try {
    $response = $client->get('http://demo.ckan.org/api/3/action/package_list');
    $data = $response->getBody();
  }
  catch (RequestException $e) {
    watchdog_exception('my_module', $e->getMessage());
  }

You can get a full list of Exception types simply by listing the contents of<drupal_root>/vendor/guzzlehttp/guzzle/src/Exception. Utilizing this list allows you to provide different behavior based on exception type.

At the time of writing, the contents of that is as follows:


  BadResponseException.php
  ClientException.php
  ConnectException.php
  GuzzleException.php
  RequestException.php
  SeekException.php
  ServerException.php
  TooManyRedirectsException.php
  TransferException.php

Guzzle clients use a handler and middleware system to send HTTP requests. You can refer to the documentation for more information about creating your own handlers and middleware to allow for more fine grained control of your HTTP workflow.