Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Web Development

Una guida per principianti all'HTTP e REST

by
Difficulty:IntermediateLength:LongLanguages:

Italian (Italiano) translation by Danilo Maccioni (you can also view the original English article)

L'HyperText Transfer Protocol (protocollo di trasferimento di un ipertesto) è l'anima del web. Viene usato ogni volta che trasferite un documento, o effettuate una richiesta AJAX. Ma sorprendentemente l'HTTP è un parente sconosciuto tra gli sviluppatori web.

Questa introduzione vuole dimostrare come l'insieme dei principi di progettazione, conosciuti come REST, sostiene l'HTTP, e vi permette di sfuttare appieno la sua potenza costruendo interfacce che possono essere usate da quasi ogni dispositivo o sistema operativo.

Tutorial ripubblicato

Ogni due settimane, ripercorriamo alcune delle pubblicazioni preferite dai nostri lettori, lungo l'arco temporale del sito. Questo tutorial fu pubblicato inizialmente nel novembre del 2010.


Perché REST?

REST è un modo semplice per organizzare le interazioni tra sistemi indipendenti.

REST è un modo semplice per organizzare le interazioni tra sistemi indipendenti. La sua popolarità ha iniziato a crescere dal 2005, ed ispira la progettazione di servizi, quali ad esempio le API di Twitter. Questo è dovuto al fatto che il REST permette un'agile interazione tra client diversi, come telefoni cellulari o altri siti web. In teoria, il REST non è vincolato al web, ma è quasi sempre adottato in tal senso, e fu ispirato dall'HTTP. Di conseguenza, il REST può essere utilizzato dovunque giri l'HTTP.

L'alternativa è costruire delle convenzioni relativamente complesse in cima all'HTTP. Spesso, ciò da forma a nuovi linguaggi basati sull'XML. L'esempio più noto è il SOAP. Dovreste imparare da zero una nuova serie di convenzioni, ma non sfruttereste appieno la potenza dell'HTTP. Dato che il REST fu ispirato dall'HTTP e ne sfrutta i punti di forza, è la maniera migliore per imparare il funzionamento dell'HTTP. 

Dopo una panoramica iniziale, esamineremo ciascuno dei blocchi fondamentali dell'HTTP: le URLs, i verbi HTTP e i codici di risposta. Studieremo anche come usarli in maniera RESTful. Lungo il percorso, illustreremo la teoria con una applicazione di esempio, che simulerà la gestione dei dati relativi ai clienti di una società, attraverso un'interfaccia web.


HTTP

L'HTTP è il protocollo che permette di inviare e ricevere documenti attraverso il web.

L'HTTP è il protocollo che permette di inviare e ricevere documenti attraverso il web. Un protocollo è un insieme di regole che determina quali messaggi possono essere scambiati, e quali messaggi rappresentano risposte appropriate ad altri. Un altro protocollo noto è il POP3, che potreste usare per ricevere le email nel vostro hard disk.

Nell'HTTP, ci sono due diversi ruoli: server and client. In genere, è il client ad avviare la conversazione; il server risponde. L'HTTP è costituito da testo; ovvero i messaggi sono essenzialmente porzioni di testo, sebbene il loro corpo possa contenere anche altri media.  L'utilizzo del testo rende semplice monitorare un interscambio HTTP.

I messaggi HTTP sono costituiti da un intestazione (header) ed un corpo (body). Il body spesso può rimanere vuoto; esso contiene le informazioni che volete trasmettere via rete, e fruirne secondo le istruzioni contenute nell'header. L'header contiene metadati, come ad esempio le informazioni di codifica; ma, nel caso di una richiesta, può anche contenere gli importanti metodi HTTP. Nello stile REST, noterete come spesso le informazioni dell'intestazione siano più significative del corpo stesso.


Spiando l'HTTP all'opera

Se usate Chrome e i suoi strumenti di sviluppo, oppure Firefox con l'estensione Firebug installata, cliccate sul pannello Net, ed impostatelo su attivo. Avrete la possibilità di osservare in dettaglio le richieste HTTP mentre navigate. Per esempio:

Screenshot of Firebug Net panel

Un altro utile metodo per prendere confidenza con l'HTTP è di usare un client dedicato, come ad esempio cURL.

cURL è uno strumento da linea di comando che è disponibile su tutti i principali sistemi operativi.

Una volta che avrete installato cURL, digitate:

Ciò vi mostrerà l'intera conversazione HTTP. Le richieste sono precedute da >, mentre le risposte sono precedute da <.


Le URL

Le URL sono il modo in cui identificate le cose con le quali volete operare. Possiamo affermare che ogni URL identifica una risorsa. Queste sono esattamente le stesse URL che vengono assegnate alle pagine web. Infatti, le pagine web sono un tipo di risorsa. Prendete un esempio più originale, e considerate la nostra applicazione di prova, che gestisce la lista dei clienti di un'azienda.

identificherà i nostri clienti, mentre

identificherà lo specifico cliente, chiamato 'jim', supponendo che sia l'unico con quel nome.

In questi esempi, generalmente non includiamo l'hostname nell'URL, dal momento che dal nostro punto di vista è irrilevante come sia organizzata l'interfaccia. Ciò nonostante, l'hostname è importante per assicurarsi che l'identificatore della risorsa sia univoco in tutto il web. Spesso diciamo che si invia la richiesta per una risorsa ad un host. L'host è incluso nell'intestazione, ma separato dal percorso della risorsa, che è posto in cima all'intestazione della richiesta.

Le risorse si comprendono meglio considerandole sostantivi. Per esempio, la seguente non è RESTful:

Questo perché nell'URL è descritta un azione. Questo è un punto fondamentale per distinguere i sistemi RESTful da quelli non-RESTful.

Infine, le URL devono essere essenzialmente precise; tutto quel che è necessario per identificare univocamente una risorsa dovrebbe stare nella URL. Non dovreste aver bisogno di includere dati identificativi nella richiesta. In questo modo, le URL fungono da mappa per tutti i dati gestiti dalla vostra applicazione.

Ma come specificare un azione? Per esempio, come dire che volete creare un nuovo record utente piuttosto che richiamarlo? Qui è dove entrano in gioco i verbi HTTP.


Verbi HTTP

Ogni richiesta specifica un determinato verbo HTTP, o metodo, nella sua intestazione. Questa è la prima parola interamente maiuscola nell'intestazione della richiesta. Per esempio,

significa che verrà usato il metodo GET, mentre

significa che sara usato il metodo DELETE.

I verbi HTTP comunicano al server cosa fare con i dati identificati dalla URL.

I verbi HTTP comunicano al server cosa fare con i dati identificati dalla URL. La richiesta può opzionalmente contenere informazioni addizionali nel suo corpo, che potrebbero essere richieste per svolgere l'operazione - ad esempio, dati che volete archiviare con la risorsa. In cURL potete aggiungere questi dati tramite l'opzione -d.

Se avete mai creato moduli HTML, avrete confidenza con due tra i più noti verbi dell'HTTP: GET e POST. Ma ci sono molti altri verbi disponibili. I più importanti per costruire delle API RESTful sono GETPOST, PUT e DELETE. Sono disponibili altri metodi, come ad esempio HEAD e OPTIONS, ma sono più rari (se volete conoscere tutti gli altri metodi HTTP, la fonte ufficiale è lo IETF).

GET

GET è il tipo di metodo di richiesta HTTP più semplice; quello che il browser usa ogni volta che cliccate su un link o inserite una URL nella barra degli indirizzi. Ordina al server di trasmettere al client le informazioni identificate nella URL. Le informazioni lato server non dovrebbero essere modificate in risultato ad una richiesta GET. In questo senso, una richiesta GET è di sola lettura, ma certamente una volta che il client riceve le informazioni, è libero di compiere ogni operazione su di esse - ad esempio formattarle per visualizzarle.

PUT

Una richiesta PUT viene usata quando si vuole creare o aggiornare la risorsa identificata dalla URL. Per esempio,

potrebbe creare un cliente di nome Robin sul server. Noterete come il REST sia completamente agnostico; nella richiesta non c'è qualcosa che istruisce il server su come vadano creati i dati - ma solo che deve farlo. Questo vi permette facilmente di sostituire le tecnologie del backend in caso le necessità dovessero aumentare. Le richieste PUT contengono nel corpo le informazioni da usare per l'aggiornamento o la creazione. In cURL, potete aggiungere informazioni alla richiesta con l'opzione -d.

DELETE

Il DELETE, dovrebbe funzionare inversamente al PUT; dovrebbe essere usato quando volete cancellare la risorsa identificata dalla URL della richiesta.

Questo eliminerà tutte le informazioni associate alla risorsa identificata da /clients/anne.

POST

POST viene utilizzato quando si desidera che il processo che avviene sul server possa essere ripetuto, in caso la richiesta POST venga ripetuta (cioè, non sono idempotenti; appofondiremo più avanti). Inoltre, le richieste POST potrebbero causare l'elaborazione del corpo come un subordinato della URL a cui vi riferite.

In parole povere:

non dovrebbe causare la modifica della risorsa /clients/ stessa, ma una risorsa la cui URL inizi con /clients/. Per esempio, potrebbe aggiungere un nuovo cliente all'elenco, con un id generato dal server.

Le richieste PUT vengono facilmente usate al posto delle richieste POST, e viceversa. Alcuni sistemi ne usano soltanto uno, altri usano POST per operazioni di creazione e PUT per quelle di aggiornamento (dal momento che la richiesta PUT fornisce sempre la URL completa), altri ancora usano POST per gli aggiornamenti e PUT per la creazione. 

Spesso, le richieste POST vengono usate per azionare operazioni sul server che esulano dal paradigma Create/Update/Delete; ma questo, ad ogni modo, va oltre i propositi del REST. Nel nostro esempio, adotteremo PUT in ogni caso.


Classificazione dei metodi HTTP

Metodi sicuri ed insicuri:
I metodi sicuri sono quelli che non alterano mai le risorse. L'unico metodo sicuro, tra i quattro elencati in precedenza, è il GET. Gli altri sono insicuri, poiché potrebbero apportare modifiche alle risorse.

Metodi idempotenti:
Questi metodi producono sempre lo stesso risultato, non importa quante volte la richiesta venga ripetuta: essi sono GET, PUT e DELETE. L'unico metodo non idempotente è il POST. PUT e DELETE sono considerati idempotenti e ciò potrebbe stupire, ma in effetti è molto semplice da spiegare: ripetendo il metodo PUT con il medesimo corpo, esso dovrebbe modificare una risorsa in maniera sempre identica a quella descritta nel PUT precedente: niente cambia! Analogamente, non avrebbe senso eliminare una risorsa due volte. Ne consegue che non importa quante volte una richiesta PUT o DELETE venga ripetuta, il risultato dovrebbe coincidere a quello di una singola esecuzione.

Ricordate: siete voi, i programmatori, che decidete cosa far accadere quando viene usato un determinato metodo. Non c'è nulla a riguardo nell'implementazione HTTP che in automatico crei, elenchi, cancelli o modifichi le risorse. Dovrete essere accorti nell'applicare correttamente il protocollo HTTP, e nel consolidare questa semantica per conto vostro. 


Rappresentazioni

Il client HTTP e il server HTTP scambiano informazioni riguardo le risorse identificate dalle URL.

Possiamo riassumere ciò che abbiamo imparato finora nel seguente modo: il client HTTP e il server HTTP scambiano informazioni riguardo le risorse identificate dalle URL.

Diciamo che la richiesta e la risposta contengono una rappresentazione della risorsa. Con rappresentazione, intendiamo informazione, in un determinato formato, riguardo lo stato della risorsa attuale o come dovrà essere in futuro. Sia l'intestazione che il corpo sono elementi della rappresentazione.

Le intestazioni HTTP, che contengono metadati, sono strettamente definite dalle specifiche HTTP; possono soltanto contenere testo semplice e devono essere formattate in una precisa maniera.

Il corpo può contenere informazioni in qualsiasi formato, questo è il punto forte dell'HTTP. Sappiate che potete inviare testo semplice, immagini, HTML e XML in un qualsiasi idioma. Attraverso i metadati della richiesta o URL differenti, potete scegliere tra differenti rappresentazioni della stessa risorsa. Per esempio, potete inviare una pagina web ai browser e JSON alle applicazioni.

La risposta HTTP deve specificare il tipo di contenuto del corpo. Questo deve essere fatto nell'intestazione, nel campo Content-Type; ad esempio:

Per semplicità, la nostra applicazione di esempio invia e riceve JSON, ma un applicazione dovrebbe essere strutturata in modo da poter cambiare il formato delle informazioni, per adattarsi alle esigenze dei clienti o utenti.


Librerie client HTTP

cURL è, spesso, la soluzione client HTTP prediletta dagli sviluppatori web.

Per testare i diversi metodi di richieste, avete bisogno di un client, che vi permetta di specificare quale metodo adottare. Sfortunatamente, i moduli HTML non fanno al caso nostro, dal momento che supportano soltanto richieste GET e POST. Nella vita reale, le API vengono interpellate sistematicamente attraverso una applicazione client separata, oppure tramite il javascript nel browser.

Questa è la ragione per cui, in aggiunta al server, è essenziale che nel nel linguaggio di programmazione da voi scelto si abbia un buon supporto di client HTTP.

Una libreria di client HTTP molto popolare è, ancora, cURL. Avete già avuto occasione di conoscere il comando cURL in questo stesso tutorial. cURL include sia un programma da linea di comando indipendente, che una libreria che può essere usata da vari linguaggi di programmazione. cURL è la soluzione adottata più di frequente dagli sviluppatori PHP. Altri linguaggi, com ad esempio il Python, offrono più librerie client HTTP native.


Impostare una applicazione di esempio

Voglio mettere in evidenza il più possibile la funzionalità a basso livello.

Il nostro esempio di applicazione PHP è estremamente essenziale. Voglio mettere in evidenza il più possibile la funzionalità a basso livello, senza l'ausilio delle magie dei framework. Non voglio utilizzare delle API reali, come quelle di Twitter, perché sono soggette a modifiche improvvise, avreste bisogno di impostare l'autenticazione, che potrebbe rappresentare un fastidio, inoltre, ovviamente, non potreste studiarne l'implementazione.

Per eseguire l'applicazione di esempio, avremo bisogno di installare PHP5 e un web server, con un meccanismo per far andare il PHP.  La versione dovrebbe essere almeno la 5.2 per avere a disposizione le funzioni json_encode() e json_decode().

Per i server, la scelta ricade comunemente su Apache con il mod_php, ma sentitevi liberi di usare qualsiasi alternativa con cui vi trovate comodi. C'è una configurazione di esempio per Apache, che contiene le regole di rewrite per aiutarvi a configurare rapidamente l'applicazione. Tutte le richieste alle URL che cominciano con /clients/, dovranno essere indirizzate verso il nostro file server.php.

In Apache, avete bisogno di abilitare il mod_rewrite, e di inserire le configurazioni del suddetto mod_rewrite da noi fornite nelle configurazioni di Apache o nel vostro file .htaccess. In questo modo, il server.php risponderà a tutte le richieste provenienti dal server. Dovreste ottenere lo stesso da Nginx, o qualsiasi server alternativo decidiate di usare.


Funzionamento dell'applicazione d'esempio

Sono due i fattori per processare le richieste nel REST. Il primo fattore è di effettuare un operazione diversa, a seconda del metodo HTTP - anche quando le URL sono le stesse. Nel PHP, esiste una variabile nell'array globale $_SERVER, che determina quale metodo è stato utilizzato per fare una richiesta:

Questa variabile contiene il nome del metodo in formato stringa, per esempio 'GET', 'PUT', e così via,

L'altro fattore è conoscere quale URL è stata richiesta. Per conoscerla, usiamo un altra variabile standard del PHP:

Questa variabile contiene la URL a partire dalla prima slash in avanti. Per esempio, se il nome dell'host fosse 'example.com', 'http://example.com/' ritornerebbe '/', mentre 'http://example.com/test/' ritornerebbe '/test/'.

Proviamo a determinare quale URL è stata chiamata. Consideriamo soltanto le URL che cominciano con 'clients'. Tutte le altre non sono valide.

Abbiamo due possibili soluzioni: 

  • La risorsa sono i clienti, in questo caso, restituiamo un elenco completo
  • C'è un altro identificatore

Se è presente un altro identificatore, presumiamo si tratti del nome del cliente, e, a sua volta, lo dirigiamo verso una funzione differente, a seconda del metodo. Usiamo un costrutto switch, che in una reale applicazione andrebbe evitato:


Codici di risposta

I codici di risposta HTTP regolano il modo di informare il client sull'esito della sua richiesta.

Potreste aver notato che l'applicazione di esempio usa l'header() PHP, passandogli come argomenti alcune strane stringhe. La funzione header() stampa le intestazioni HTTP e si assicura che siano formattate in modo appropriato. Le intestazioni dovrebbero essere il primo elemento della risposta, perciò non dovreste restituire niente prima di aver completato le intestazioni. A volte, il vostro server HTTP potrebbe essere configurato per aggiungere altre intestazioni, in aggiunta a quelle specificate nel vostro codice.

Le intestazioni contengono ogni tipo di meta informazione; per esempio, la codifica del testo utilizzata nel corpo del messaggio oppure il MIME type del contenuto del corpo. Nel nostro caso, stiamo specificando esplicitamente i codici di risposta HTTP. I codici di risposta HTTP regolano il modo di informare il client sull'esito della sua richiesta. Normalmente, PHP restituisce un codice di risposta 200, che significa che la risposta è positiva.

Il server dovrebbe restituire il codice di riposta più appropriato; in questo modo, il client, potrà tentare di rimediare agli errori, ammesso che ce ne siano. Molte persone conoscono il noto codice di risposta 404 Not Found, ad ogni modo, ce ne sono molti altri disponibili per coprire una vasta gamma di situazioni.

Ricordate che il significato dei codici di risposta HTTP non è estremamente preciso; questo è dovuto al fatto che lo stesso HTTP è piuttosto generico. Dovreste impegnarvi ad utilizzare il codice di risposta che aderisca il più possibile al caso in questione. Come già detto, non preoccupatevi troppo se non trovate una corrispondenza esatta.

Qui ci sono i codici di risposta HTTP che spesso vengono usati nel REST:

200 OK

Questo codice di risposta indica che la richiesta era valida.

201 creato

Questo indica che la richiesta era valida e che una risorsa è stata creata. Viene utilizzato per confermare il successo di una richiesta PUT o POST.

400 richiesta non valida

La richiesta non è stata formata in modo corretto. Questo accade specialmente con le richieste POST e PUT, quando le informazioni non superano la validazione, o sono nel formato sbagliato.

404 non trovato

Questa risposta indica che la risorsa richiesta non può essere localizzata. Questo generalmente viene restituito da tutte le risposte che puntano ad una URL a cui non corrisponde una risorsa.

401 non autorizzato

Questo errore indica che avete bisogno di effettuare l'autenticazione prima di accedere alla risorsa.

405 metodo non permesso

Il metodo utilizzato non è supportato per la risorsa in questione.

409 conflitto

Questo indica un conflitto. Per esempio, state effettuando una richiesta PUT per creare la risorsa una seconda volta. 

500 errore interno al server

Quando tutte le possibilità falliscono; la risposta 500 è usata quando il processo fallisce lato server, in circostanze impreviste, che causano l'insorgere dell'errore.


Esercitarsi con l'applicazione d'esempio

Iniziamo con richiedere semplicemente le informazioni dall'applicazione. Vogliamo i dettagli del cliente 'jim', perciò inviamo una semplice richieta GET alla URL di questa risorsa:

Questo mostrerà l'intestazione completa del messaggio. L'ultima riga nella risposta sarà il corpo del messaggio; in questo caso, sarà un oggetto in notazione JSON contenente l'indirizzo di Jim (ricordate che omettere il nome di un metodo, equivarrà ad effettuare una richiesta GET); inoltre dovrete sostituire localhost:80 con il nome del server e della porta che state utilizzando).

Poi, possiamo ottenere le informazioni per tutti i clienti in una sola volta.

Per creare un nuovo cliente di nome Paul...

e riceverete la lista di tutti i clienti che ora contengono Paul come conferma.

Infine, per eliminare un cliente:

Scoprirete che l'oggetto JSON restituito non contiene più alcuna informazione riguardo Anne.

Se provate a recuperare un cliente inesistente, per esempio:

Dovreste ottenere un errore 404, mentre se provate a creare un cliente che esiste già:

curl -v -X PUT http://localhost:80/clients/anne

Invece dovreste ricevere un errore 409.


Conclusioni

In generale, meno presupposti oltre l'HTTP vi date, meglio è.

È importante ricordare che l'HTTP è stato concepito per la comunicazione tra sistemi, che non condividono nulla se non la conoscenza dello stesso protocollo. In generale, meno presupposti oltre l'HTTP vi date, meglio è: questo consentirà l'accesso alle vostre API dalla più ampia gamma di programmi e e dispositivi.

In questo tutorial ho usato PHP, perché è il linguaggio più familiare ai lettori di Nettuts+. Detto ciò, anche se il PHP è disegnato per il web, probabilmente non è il miglior linguaggio da utilizzare per lavorare secondo il criterio REST, dal momento che gestisce le richieste PUT in una maniera totalmente diversa rispetto a GET o POST.

Oltre al PHP, potreste considerare le seguenti alternative:

  • I vari framework di Ruby (Rails e Sinatra)
  • C'è un ottimo supporto per il REST in Python. I semplici Django e WebOb, oppure Werkzeug dovrebbero funzionare.
  • node.js ha un eccellente supporto per il REST

Tra le applicazioni che tentano di rispettare i principi REST, un esempio classico è il Protocollo di Pubblicazione Atom, anche se onestamente nella pratica non è usato spesso. Per un applicazione moderna, costruita nell'ottica di sfruttare al meglio l'HTTP, fate riferimento ad Apache CouchDB.

Buon divertimento!

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.