REST, applicazione al Web ed ai servizi RESTful

Nel precedente post vi ho raccontato delle vicende che hanno portato alla definizione del modello REST. Non è il caso di entrare nel merito della descrizione, piuttosto formale, che ne fa l’autore nella sua tesi di dottorato. Vediamo invece quali sono i concetti chiave di questa architettura e come questi siano riscontrabili nel Web e più di recente abbiano ispirato i servizi RESTful*.

Risorse e identificativi

Nel modello REST si parla di risorse e dei relativi identificativi, che corrispondono nel Web ai documenti (html, jpg, css, ecc.) e alle funzionalità identificate dagli URL. Anche i servizi RESTful utilizzano gli URL per identificare l’oggetto delle possibili interazioni tra client e server. Ad esempio i servizi RESTful di una videoteca potrebbero avere i seguenti URL:

  1. /film
    per interagire con l’intero archivio dei film
  2. /film/terminator
    per gestire il particolare film Terminator
  3. /film/terminator/attori
    per accedere all’elenco degli attori di Terminator
  4. /film/terminator/attori/schwarzenegger
    per interagire con l’interpretazione di Arnold Schwarzenegger in Terminator

Gli URL degli esempi 1 e 3 si dicono di tipo collection poiché fanno riferimento ad un insieme omogeneo di elementi (film e attori di un film), mentre gli URL 2 e 4 referenziano specifici elementi.

Salta subito all’occhio una differenza sostanziale con i servizi SOAP che tramite un unico URL possono esporre funzionalità relative a differenti soggetti (film, attori, ecc.). Questo avviene perché in SOAP l’oggetto dell’interazione tra client e server è codificato nel messaggio XML e non nell’URL.

Rappresentazione delle risorse

Abbiamo detto che nel modello REST l’interazione tra client e server ha come oggetto una risorsa. Questa risorsa però si manifesta non direttamente ma tramite delle sue rappresentazioni. Una rappresentazione di una risorsa è costituita da:

  • i dati associati alla risorsa, descritti mediante una specifica codifica;
  • i metadati necessari a descrivere i suddetti dati, sotto forma di coppie nome – valore.

Per una particolare risorsa possono essere prodotte differenti rappresentazioni, ad esempio impiegando diverse sistemi di codifica della stessa.

Nel Web ad esempio la rappresentazione di una pagina HTML è costituita dai byte dell’HTML a cui si aggiungono le intestazioni HTTP che permettono al browser di interpretarli correttamente (Content-Type, charset, ecc.). Inoltre la rappresentazione di una risorsa può essere il frutto di una negoziazione tra browser e server. Questo aspetto emerge se analizziamo le intestazioni HTTP scambiate tra browser e server nel caso di accesso ad una pagina web:

  • nella richiesta del browser è presente un header HTTP con l’indicazione di quali sono le tipologie di rappresentazione della risorsa che il browser è in grado di gestire:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
  • nella risposta invece è presente la tipologia di rappresentazione scelta dal server per l’invio al browser della risorsa richiesta:
Content-Type:text/html; charset=UTF-8

Per i servizi RESTful questo concetto si traduce nella possibilità di realizzare una negoziazione tra client e server sul formato di codifica da utilizzare nella trasmissione dei dati, come JSON o XML, del tutto simile a quella che avviene tra browser e server web. Anche questa caratteristica differenzia i servizi RESTful da quelli SOAP che invece adottano solo messaggi XML.

Trasporto delle rappresentazioni

Il modello REST prevede una interazione di tipo client-server tra i nodi della rete. In queste interazioni ha luogo il trasporto, ovvero la trasmissione delle rappresentazioni delle risorse tra client e server. Per descrivere queste comunicazioni, client e server utilizzano dei “control data”, con lo scopo di dichiarare 1) l’azione richiesta dal client e 2) il significato della risposta del server.

Nel Web questo si realizza mediante il protocollo di trasporto HTTP, che utilizza:

  1. dei “verbi” per specificare il tipo di richiesta che il client rivolge al server web;
  2. degli “status code” per indicare al browser l’esito della richiesta effettuata.

I verbi più utilizzati da un browser sono GET, per richiedere una “pagina” dato il suo URL, e POST per inviare al server i dati inseriti da un utente in un form HTML. Lo status code più noto del Web è certamente il 404 “pagina non trovata”.

I verbi HTTP ricoprono un ruolo del tutto simile nei servizi RESTful. Mediante questi verbi il client indica al server quale tipo di operazione intende effettuare su una particolare risorsa. Per questa ragione nel contesto dei servizi RESTful vengono impiegati, oltre a GET e POST, ulteriori verbi HTTP. Di seguito il significato di quelli maggiormente utilizzati, raggruppati in base al risultato atteso in caso di esecuzione multipla (idempotenza).

Operazioni idempotenti – anche se eseguite più volte su uno specifico URL, il risultato non deve cambiare rispetto a quello ottenibile con una singola esecuzione.

  • GET, per recuperare una rappresentazione della risorsa.
    In caso di URL di tipo collection la risposta del server dovrebbe contenere, tra l’altro, anche gli URL delle singole entità appartenenti alla collection.
    Questa operazione non deve in alcun modo modificare lo stato della risorsa richiesta.
  • PUT, crea o aggiorna una risorsa identificata dall’URL specificato. Se la risorsa esiste già allora il server la aggiorna, altrimenti la crea, associandola all’URL specificato.
    Generalmente l’URL specificato in una richiesta di tipo PUT non è di tipo collection (vedi i precedenti esempi 1 e 3) ma identifica una specifica entità, a meno che non si voglia creare o aggiornare una intera collection.
    Poiché l’identificativo della risorsa è specificato dal client, se questa non esiste il server è tenuto a crearla utilizzando proprio questo identificativo. Non è detto però che il server possa accettare che sia il client a scegliere l’identificativo delle nuove risorse, ad esempio perché questo è un numero progressivo gestito dal server. In questi casi il server, ad una richiesta PUT per una nuova risorsa, restituisce un errore.
  • DELETE, cancella una risorsa identificata dall’URL specificato.
    Come per PUT, generalmente l’URL specificato in una richiesta di tipo DELETE non è di tipo collection.

Operazioni non idempotenti – il risultato può cambiare ad ogni esecuzione dell’operazione.

  • POST, per la creazione di una nuova risorsa affidata ad un URL che rappresenta l’entità “padre” della nuova risorsa.
    Generalmente l’URL specificato in una richiesta di tipo POST è di tipo collection, poiché il client vuole aggiungere una nuova risorsa nella collection indicata.

Nel caso si stia realizzando un servizio RESTful con una semantica non immediatamente riconducibile a quella di una delle suddette operazioni, bisogna comunque scegliere il verbo che si avvicina di più allo scopo del servizio tra quelli definiti dagli standard RFC 7231  (GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE) e RFC 5789 (PATCH), facendo massima attenzione a rispettare la caratteristica di idempotenza del verbo scelto.

Come anticipato, l’esito delle richieste RESTful viene indicato dal server mediante lo status code dell’HTTP. Di seguito alcuni possibili esiti delle principali operazioni:

  • GET: 200 (Ok) se il server è in grado di restituire la risorsa associata all’URL richiesto, 404 (Not Found) se l’URL non esiste;
  • PUT: 200 (Ok) o 204 (No Content) se la risorsa viene creata o aggiornata come richiesto, 405 (Method Not Allowed) se il server non accetta di eseguire l’operazione richiesta sull’URL specificato (ad esempio in caso di richiesta di creazione di nuove risorse);
  • POST: 201 (Created) se il server è in grado di creare la nuova risorsa;
  • DELETE: 200 (Ok) o 204 (No Content) se il server è in grado di rimuovere la risorsa associata all’URL richiesto, 404 (Not Found) se l’URL non esiste;

In estrema sintesi potremmo dire che i servizi RESTful affidano tutta la gestione del trasposto delle rappresentazioni al protocollo HTTP: la semantica della richiesta del client è codificata nei verbi HTTP mentre il significato delle risposte è comunicato al client mediante gli status code. Questa costituisce una ulteriore differenza con i servizi SOAP che invece incorporano nel messaggio XML la descrizione della request e della response.

HATEOAS

Il modello REST è definito dall’autore come un “architectural style for distributed hypermedia systems“. Non sorprende quindi che in questo modello abbia un ruolo centrale il concetto di ipertesto: “Hypertext As The Engine Of Application State” da cui il discutibile acronimo HATEOAS. Le risorse del modello REST sono infatti collegate mediante link che permettono di navigare il “distributed hypermedia systems”.

Nel Web questi link sono presenti sia nei documenti HTML (i tag <a>), sia nei messaggi del protocollo HTTP, si pensi alla risposta HTTP 301 “Moved Permanently”. Allo stesso modo anche i servizi RESTful sono tenuti ad incorporare nei messaggi e nel protocollo HTTP l’informazione degli URL associati alla risorsa corrente. Ad esempio quando il client effettua una GET per un URL, il messaggio di risposta deve contenere gli URL delle risorse collegate all’URL richiesto. Oppure quando il client effettua una POST per creare una nuova risorsa, il server deve rispondere indicando l’URL della risorsa appena creata, nonché gli URL da utilizzare per manipolarla.

In questo modo, analizzando le risposte del server, è possibile “navigare” il servizio RESTful e scoprire tutte le funzionalità disponibili. Inoltre è possibile per il client rendere dinamico il puntamento ai diversi URL del server poiché è questo a fornirli di volta in volta.

Purtroppo non esiste una sintassi standard per incorporare questi link nei messaggi RESTful. La soluzione più adottata è quella definita nello standard ATOM.

Conclusioni

In questo post abbiamo descritto il modello REST utilizzando la sua implementazione più nota, ovvero il Web, e la più recente applicazione costituita dai servizi RESTful. Ho volutamente trascurato altri importanti aspetti del modello che ci serviranno, in un prossimo post, per rispondere alle seguenti domande:

  • i servizi RESTful sono migliori di quelli SOAP?
  • perché è stata recuperata una tecnologia non certo recente per disegnare un nuovo modello di servizi web?
  • il modello REST deve essere preso in considerazione nella progettazione di applicazioni web?
  • perché sono ossessionato da questo argomento?

______

* Anche se i servizi RESTful non obbligano ad utilizzare un particolare protocollo, in questo post faccio riferimento all’implementazione più diffusa, ovvero quella che sfrutta l’HTTP.

Lascia un commento