Proviamo a gettare un nuovo standard per la gestione delle sorgenti e per la presentazione di dati nelle istanze Drupal che consumano servizi. Perchè ne abbiamo bisogno e come i Guzzle Service Description possono salvarci la vita.
di Adriano Cori
4. HTTP
DRUPAL COME FRONT-END CHE CONSUMA SERVIZI REST:
Adriano Cori, @bmeme
DrupalDay Roma
3 Marzo 2017
CLIENT MANAGER
5. HTTP CLIENT MANAGER
“L'HyperText Transfer Protocol (HTTP) è un protocollo a livello
applicativo usato come principale sistema per la trasmissione
d'informazioni sul web ovvero in un'architettura tipica client-
server.”- https://it.wikipedia.org/wiki/Hypertext_Transfer_Protocol
DRUPAL COME FRONT-END CHE CONSUMA SERVIZI REST:
6. HTTP REQUEST
DRUPAL COME FRONT-END CHE CONSUMA SERVIZI REST:
HTTP CLIENT MANAGER
• POST
• GET
• PUT, PATCH
• DELETE
• OPTIONS
• HEAD
• TRACE
• CONNECT
> Request Method
• CREATE
• RETRIEVE
• UPDATE
• DELETE
> Request URI
Lo uniform resource identifier indica
l'oggetto della richiesta
> Request Header
• Host
• User-Agent
• Accept
7. HTTP RESPONSE
DRUPAL COME FRONT-END CHE CONSUMA SERVIZI REST:
HTTP CLIENT MANAGER
• 200
• 301
• 302
• 307
• 400
• 404
• 500
• 505
> Response Status
Ok
Moved Permanently
Found
Temporary Redirect
Bad Request
Not Found
Internal Server Error
HTTP Version Unsupported
> Response body
Contiene il contenuto della
risposta
> Response Header
• Date
• Content-Type
• Cache-Control
8. DRUPAL COME FRONT-END CHE CONSUMA SERVIZI REST:
HTTP CLIENT MANAGER
“REpresentational State Transfer (REST) è un tipo di architettura
software per i sistemi di ipertesto distribuiti come il World Wide
Web.”- https://it.wikipedia.org/wiki/Representational_State_Transfer
“REST defines a set of architectural principles by which you can
design Web services that focus on a system's resources, including
how resource states are addressed and transferred over HTTP by a
wide range of clients written in different languages.”
- https://www.ibm.com/developerworks/webservices/library/ws-restful
/**
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
@see DrupalsparkfabrikPaoloPustorino::restInPieces()
9. REST SERVICE
DRUPAL COME FRONT-END CHE CONSUMA SERVIZI REST:
HTTP CLIENT MANAGER
> HTTP Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
[
{
"id": 1,
"title": "Ma che bella notizia",
"body": "Lorem ipsum non passa mai di moda",
"date": "2017-03-03 10:15:32”
},
{
"id": 2,
"title": "Inizia il talk di @aronne",
"body": "Lorem ipsum come se piovesse",
"date": "2017-03-03 10:02:54”
}
]
GET /api/news?date=2017-03-03 HTTP/1.1
Host: example.com
User-Agent: curl/7.43.0
Accept: application/json
> HTTP Request
10. DRUPAL COME FRONT-END CHE CONSUMA SERVIZI REST:
HTTP CLIENT MANAGER
“An HTTP client uses HTTP to connect to a web server over the
Internet to transfer documents or other data. The most well known
types of HTTP Clients include web browsers.”- https://en.wikipedia.org/wiki/
Category:Hypertext_Transfer_Protocol_clients
Cosa ci mette a disposizione Drupal 8?
Drupal::httpClient()
public static function httpClient() {
return static::getContainer()->get('http_client');
}
http_client:
class: GuzzleHttpClient
factory: http_client_factory:fromOptions
11. DRUPAL COME FRONT-END CHE CONSUMA SERVIZI REST:
HTTP CLIENT MANAGER
$news = Drupal::httpClient()->request(
'GET',
'http://api.example.com/news',
['date' => '2017-03-03']
);
“Ahah..ma come Guzzle se fa dico io”
Alternative?
12. ALTERNATIVE
DRUPAL COME FRONT-END CHE CONSUMA SERVIZI REST:
HTTP CLIENT MANAGER
Creare una classe che faccia da wrapper al Drupal::httpClient()
• Memorizzare l’host tanto per cominciare
• Creare dei metodi ad hoc per ogni Request
• Validazione dei parametri
• Design pattern a piacere :)
• Riusabilità del codice
• …
e poi un bel giorno….
14. REFACTORING
DRUPAL COME FRONT-END CHE CONSUMA SERVIZI REST:
HTTP CLIENT MANAGER
Creare una classe astratta che faccia da bla bla bla…
• Programmazione orientata agli insulti
• Il nuovo codice va ritestato
• la tua ragazza ti lascia
• il corvo si sbagliava riguardo alla pioggia
• belle sbuffate
• io manco ce volevo veni’
• e mettemocela n’altra if…
• AggileGiggi me spiccia casa
ma poi alla fine….
16. REFACTORING
DRUPAL COME FRONT-END CHE CONSUMA SERVIZI REST:
HTTP CLIENT MANAGER
Come si potrebbe migliorare ancora il nostro codice?
• Rendendolo (se non lo si era già fatto) il più astratto possibile
• Rimuovendo dal codice info relative agli endpoint, risorse e
parametri, spostandole invece su dei file di configurazione
• cancellandolo…
18. DRUPAL COME FRONT-END CHE CONSUMA SERVIZI REST:
HTTP CLIENT MANAGER
Http Client Manager introduces a new Guzzle based plugin which
allows you to manage HTTP clients using Guzzle Service Descriptions
via JSON files, in a simple and efficient way:
"Service descriptions define web service APIs by documenting each
operation, the operation's parameters, validation options for each
parameter, an operation's response, how the response is parsed, and
any errors that can be raised for an operation. Writing a service
description for a web service allows you to more quickly consume a
web service than writing concrete commands for each web service
operation.”
You will no longer need to write down Http services calls each times
specifying endpoints and parameters in a totally decentralized way.
19. DRUPAL COME FRONT-END CHE CONSUMA SERVIZI REST:
HTTP CLIENT MANAGER
> Http Services Api definition via *.http_services_api.yml file
example_services:
title: "Example Services - posts API"
api_path: "src/api/example_services.json"
base_url: "http://api.example.com"
auth_services:
title: "Another Example Services - auth API"
api_path: "src/api/auth_services.json"
base_url: “http://auth.services.com"
> Overridable Services Api definition via settings.php file
$settings['http_services_api']['example_services'] = [
'title' => 'Example Services - posts API (Development)',
'base_url' => 'http://api.example.dev',
];
> Ad Hoc client definition via *.services.yml file
services:
example_api.http_client:
parent: http_client_manager.client_base
arguments: ['example_services']
21. DRUPAL COME FRONT-END CHE CONSUMA SERVIZI REST:
HTTP CLIENT MANAGER
> Multiple ways to instantiate http clients
// Client instantiation via http_client_manager service factory method.
$client = Drupal::service('http_client_manager.factory')->get('example_services');
// Client instantiation via service.
$client = Drupal::service(‘example_api.http_client');
> Multiple ways to execute http requests
// Call method usage.
$latestPosts = $client->call('FindPosts', ['limit' => '10', 'sort' => 'desc']);
// Magic method usage.
$latestPosts = $client->findPosts(['limit' => '10', 'sort' => 'desc']);
22. DRUPAL COME FRONT-END CHE CONSUMA SERVIZI REST:
HTTP CLIENT MANAGER
You can also create and store (bookmark) predefined requests via web UI as
Configuration Entities (exportable via Configuration Manager), and execute
them from your code in this way:
// Http Config Request usage via Config Entity static method.
$latestPosts = HttpConfigRequest::load('find_posts')->execute();
// Http Config Request usage via entity type manager.
$latestPosts = $this->entityTypeManager()
->getStorage('http_config_request')
->load('find_posts')
->execute();
23. DRUPAL COME FRONT-END CHE CONSUMA SERVIZI REST:
HTTP CLIENT MANAGER
/**
* Class HttpEventSubscriber.
*/
class HttpEventSubscriber implements EventSubscriberInterface {
/**
* {@inheritdoc}
*/
static function getSubscribedEvents() {
return [
'request.before_send' => array('onRequestBeforeSend', -1000)
];
}
/**
* Request before-send event handler
*
* @param Event $event
* Event received
*/
public function onRequestBeforeSend(Event $event) {
// your code goes here…
}
}
24. CONCLUSIONI
DRUPAL COME FRONT-END CHE CONSUMA SERVIZI REST:
HTTP CLIENT MANAGER
HTTP Client Manager in cosa ci aiuta?
• Ad evitare la dispersione del codice centralizzandone l’utilizzo
• Ad evitare di scrivere altro codice in favore di un riutilizzo delle
descrizioni dei servizi
• A risolvere un problema comune proponendosi quindi come un
nuovo standard per la gestione delle sorgenti e per la
presentazione di dati nelle istanze Drupal che consumano servizi