031.3 Lezione 1
Certificazione: |
Web Development Essentials |
---|---|
Versione: |
1.0 |
Argomento: |
031 Sviluppo Software e Tecnologie Web |
Obiettivo: |
031.3 Nozioni Base sull’HTTP |
Lezione: |
1 di 1 |
Introduzione
L'HyperText Transfer Protocol (HTTP) definisce come un client chiede al server una risorsa specifica. Il suo principio di funzionamento è abbastanza semplice: il client crea un messaggio di richiesta che identifica la risorsa di cui ha bisogno e lo inoltra al server attraverso la rete. A sua volta, il server HTTP valuta dove estrarre la risorsa richiesta e invia un messaggio di risposta al client. Il messaggio di risposta contiene dettagli sulla risorsa richiesta, seguito dalla risorsa stessa.
Più precisamente, HTTP è l’insieme di regole che definiscono come l’applicazione client deve formattare i messaggi di request che saranno inviati al server. Il server segue quindi le regole HTTP per interpretare la richiesta e formattare i messaggi di reply. Oltre a richiedere o trasferire il contenuto richiesto, i messaggi HTTP contengono informazioni extra sul client e sul server coinvolti, sul contenuto stesso, e anche sulla sua indisponibilità. Se una risorsa non può essere inviata, un codice nella risposta spiega il motivo dell’indisponibilità e, se possibile, indica dove la risorsa è stata spostata.
La parte del messaggio che definisce i dettagli della risorsa e altre informazioni di contesto è chiamata header del messaggio. La parte che segue l’intestazione, che contiene il contenuto della risorsa corrispondente, è chiamata il payload del messaggio. Sia i messaggi di richiesta sia quelli di risposta possono avere un payload, ma nella maggior parte dei casi, solo il messaggio di risposta ne ha uno.
La Richiesta del Client
Il primo stadio di uno scambio di dati HTTP tra il client e il server è iniziato dal client, quando scrive un messaggio di richiesta al server. Prendiamo, per esempio, un compito comune del browser: caricare una pagina HTML da un server che ospita un sito web, come https://learning.lpi.org/it/
. L’indirizzo, o URL, fornisce diverse informazioni rilevanti. Tre informazioni appaiono in questo particolare esempio:
-
Il protocollo: HyperText Transfer Protocol Secure (
https
), una versione criptata di HTTP. -
Il nome di rete dell’host web (
learning.lpi.org
). -
La posizione della risorsa richiesta sul server (la directory
/en/
- in questo caso, la versione inglese della home page).
Note
|
Un Uniform Resource Locator (URL) è un indirizzo che punta a una risorsa su Internet. Questa risorsa è di solito un file che può essere ottenuto da un server remoto, ma gli URL possono anche indicare contenuti e flussi di dati generati dinamicamente. |
Come il client gestisce l’URL
Prima di contattare il server, il client deve convertire learning.lpi.org
nel suo indirizzo IP corrispondente. Il client usa un altro servizio Internet, il Domain Name System (DNS), per richiedere l’indirizzo IP di un nome host da uno o più server DNS predefiniti (i server DNS sono solitamente definiti automaticamente dall’Internet Service Provider, ISP).
Con l’indirizzo IP del server, il client cerca di connettersi alla porta HTTP o HTTPS. Le porte di rete sono numeri di identificazione definiti dal Transmission Control Protocol (TCP) per interconnettere e identificare canali di comunicazione distinti all’interno di una connessione client/server. Per default, i server HTTP ricevono richieste sulle porte TCP 80 (HTTP) e 443 (HTTPS).
Note
|
Ci sono altri protocolli usati dalle applicazioni web per implementare la comunicazione client/server. Per le chiamate audio e video, per esempio, è più appropriato usare WebSocket, un protocollo di livello inferiore che è più efficiente di HTTP per trasferire flussi di dati in entrambe le direzioni. |
Il formato del messaggio di richiesta che il client invia al server è lo stesso in HTTP e HTTPS. HTTPS è già più utilizzato di HTTP, perché tutti gli scambi di dati tra client e server sono criptati, una caratteristica indispensabile per promuovere la privacy e la sicurezza sulle reti pubbliche. La connessione criptata viene stabilita tra il client e il server ancor prima che qualsiasi messaggio HTTP venga scambiato, utilizzando il protocollo crittografico Transport Layer Security (TLS). In questo modo, tutta la comunicazione HTTPS è incapsulata da TLS. Una volta decrittata, la richiesta o la risposta trasmessa su HTTPS non è diversa da una richiesta o risposta fatta esclusivamente su HTTP.
Il terzo elemento del nostro URL, /it/
, sarà interpretato dal server come la posizione o il percorso della risorsa richiesta. Se il percorso non è fornito nell’URL, verrà utilizzata la posizione predefinita /
. L’implementazione più semplice di un server HTTP associa i percorsi negli URL ai file presenti sul file system dove il server è in esecuzione, ma questa è solo una delle molte opzioni disponibili su server HTTP più sofisticati.
Il Messaggio di Richiesta
HTTP opera attraverso una connessione già stabilita tra client e server, di solito implementata in TCP e criptata con TLS. Infatti, una volta che una connessione che soddisfa i requisiti imposti dal server è pronta, una richiesta HTTP digitata a mano in testo semplice potrebbe generare la risposta del server. In pratica, tuttavia, i programmatori raramente hanno bisogno di implementare routine per comporre messaggi HTTP, poiché la maggior parte dei linguaggi di programmazione fornisce meccanismi che automatizzano la realizzazione del messaggio HTTP. Nel caso dell’URL di esempio, https://learning.lpi.org/it/
, il messaggio di richiesta più semplice possibile avrebbe il seguente contenuto:
GET /en/ HTTP/1.1 Host: learning.lpi.org User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0 Accept: text/html
La prima parola della prima riga identifica il metodo HTTP: definisce quale operazione il client vuole eseguire sul server. Il metodo GET informa il server che il client richiede la risorsa che segue: /it/
. Sia il client sia il server possono supportare più di una versione del protocollo HTTP, quindi anche la versione da adottare nello scambio di dati viene fornita nella prima riga: HTTP/1.1
.
Note
|
La versione più recente del protocollo HTTP è HTTP/2. Tra le varie differenze, i messaggi scritti in HTTP/2 sono codificati in una struttura binaria, mentre i messaggi scritti in HTTP/1.1 sono inviati in testo semplice. Questo cambiamento ottimizza la velocità di trasmissione dei dati, ma il contenuto dei messaggi è fondamentalmente lo stesso. |
L’intestazione può contenere più righe dopo la prima per contestualizzare e aiutare a identificare la richiesta al server. Il campo di intestazione Host
, per esempio, può sembrare ridondante, perché l’host del server è stato ovviamente identificato dal client per stabilire la connessione ed è ragionevole supporre che il server conosca la propria identità. Tuttavia è importante informare l’host del nome dell’host previsto nell’intestazione della richiesta, perché è pratica comune utilizzare lo stesso server HTTP per ospitare più di un sito web. (In questo scenario, ogni host specifico è chiamato virtual host.) Pertanto, il campo Host
viene utilizzato dal server HTTP per identificare a quale host si riferisce la richiesta.
Il campo di intestazione User-Agent
contiene dettagli sul programma client che fa la richiesta. Questo campo può essere usato dal server per adattare la risposta ai bisogni di uno specifico client, ma è più spesso usato per produrre statistiche sui client che usano il server.
Il campo Accept
ha un valore più immediato, perché informa il server sul formato della risorsa richiesta. Se il client è indifferente al formato della risorsa, il campo Accept
può specificare */*
come formato.
Ci sono molti altri campi di intestazione che possono essere usati in un messaggio HTTP, ma i campi mostrati nell’esempio sono sufficienti per richiedere una risorsa al server.
Oltre ai campi dell’intestazione della richiesta, il client può includere altri dati complementari nella richiesta HTTP che sarà inviata al server. Se questi dati consistono solo in semplici parametri di testo, nel formato nome=valore
, possono essere aggiunti al percorso del metodo GET. I parametri sono incorporati nel percorso dopo un punto interrogativo e sono separati da caratteri ampersand (&
):
GET /cgi-bin/receive.cgi?name=LPI&email=info@lpi.org HTTP/1.1
In questo esempio, /cgi-bin/receive.cgi
è il percorso dello script sul server che elaborerà ed eventualmente utilizzerà i parametri name
e email
, ottenuti dal percorso della richiesta. La stringa che corrisponde ai campi, nel formato name=LPI&email=info@lpi.org
, è chiamata query string ed è fornita allo script receive.cgi
dal server HTTP che riceve la richiesta.
Quando i dati sono costituiti da brevi campi di testo, è più appropriato inviarli nel payload del messaggio. In questo caso si deve usare il metodo HTTP POST affinché il server riceva ed elabori il payload del messaggio, secondo le specifiche indicate nell’intestazione della richiesta. Quando si usa il metodo POST, l’intestazione della richiesta deve fornire la dimensione del carico utile che verrà inviato in seguito e come viene formattato il corpo:
POST /cgi-bin/receive.cgi HTTP/1.1 Host: learning.lpi.org Content-Length: 1503 Content-Type: multipart/form-data; boundary=------------------------405f7edfd646a37d
Il campo Content-Length
indica la dimensione in byte del carico utile e il campo Content-Type
indica il suo formato. Il formato multipart/form-data
è quello più comunemente usato nei moduli HTML tradizionali che usano il metodo POST. In questo formato, ogni campo inserito nel payload della richiesta è separato dal codice indicato dalla parola chiave boundary
. Il metodo POST dovrebbe essere usato solo quando è appropriato, poiché utilizza una quantità di dati leggermente maggiore rispetto a una richiesta equivalente fatta con il metodo GET. Poiché il metodo GET invia i parametri direttamente nell’intestazione del messaggio della richiesta, lo scambio totale di dati ha una latenza inferiore, perché non sarà necessario uno stadio di connessione aggiuntivo per trasmettere il corpo del messaggio.
L’Intestazione di Risposta
Dopo che il server HTTP ha ricevuto l’intestazione del messaggio di richiesta, il server restituisce un messaggio di risposta al client. Una richiesta di file HTML ha tipicamente un’intestazione di risposta come questa:
HTTP/1.1 200 OK Accept-Ranges: bytes Content-Length: 18170 Content-Type: text/html Date: Mon, 05 Apr 2021 13:44:25 GMT Etag: "606adcd4-46fa" Last-Modified: Mon, 05 Apr 2021 09:48:04 GMT Server: nginx/1.17.10
La prima riga fornisce la versione del protocollo HTTP usata nel messaggio di risposta, che deve corrispondere alla versione usata nell’intestazione della richiesta. Poi, sempre nella prima riga, appare il codice di stato della risposta, che indica come il server ha interpretato e generato la risposta per la richiesta.
Il codice di stato è un numero di tre cifre, dove la cifra più a sinistra definisce la classe di risposta. Ci sono cinque classi di codici di stato, numerate da 1 a 5, ognuna delle quali indica un tipo di azione intrapresa dal server:
- 1xx (Informational)
-
La richiesta è stata ricevuta, continuando il processo.
- 2xx (Successful)
-
La richiesta è stata ricevuta, compresa e accettata con successo.
- 3xx (Redirection)
-
È necessario intraprendere ulteriori azioni per completare la richiesta.
- 4xx (Client Error)
-
La richiesta contiene una sintassi sbagliata o non può essere soddisfatta.
- 5xx (Server Error)
-
Il server non è riuscito a soddisfare una richiesta apparentemente valida.
La seconda e la terza cifra sono usate per indicare ulteriori dettagli. Il codice 200, per esempio, indica che è stato possibile rispondere alla richiesta senza problemi. Come mostrato nell’esempio, può essere fornita anche una breve descrizione testuale dopo il codice di risposta (OK
). Alcuni codici specifici sono di particolare interesse per assicurare che il client HTTP possa accedere alla risorsa in situazioni avverse o per aiutare a identificare il motivo del fallimento nel caso di una richiesta non riuscita:
301 Moved Permanently
-
Alla risorsa di destinazione è stato assegnato un nuovo URL permanente, fornito dal campo di intestazione
Location
nella risposta. 302 Found
-
La risorsa di destinazione risiede temporaneamente sotto un URL diverso.
401 Unauthorized
-
La richiesta non è stata applicata perché manca di credenziali di autenticazione valide per la risorsa di destinazione.
403 Forbidden
-
La risposta
Forbidden
indica che, sebbene la richiesta sia valida, il server è configurato per non fornirla. 404 Not Found
-
Il server di origine non ha trovato una rappresentazione corrente per la risorsa di destinazione o non è disposto a rivelare che ne esista una.
500 Internal Server Error
-
Il server ha incontrato una condizione inaspettata che gli ha impedito di soddisfare la richiesta.
502 Bad Gateway
-
Il server, mentre agiva come gateway o proxy, ha ricevuto una risposta non valida da un server in entrata a cui ha avuto accesso mentre tentava di soddisfare la richiesta.
Pur indicando che non è stato possibile soddisfare la richiesta, i codici di stato 4xx
e 5xx
indicano che il server HTTP è in funzione ed è in grado di ricevere richieste. I codici 4xx
richiedono un’azione da parte del client, perché l’URL o le credenziali sono sbagliate. Al contrario, i codici 5xx
indicano qualcosa di sbagliato sul lato server. Quindi, nel contesto delle applicazioni web, queste due classi di codici di stato indicano che la fonte dell’errore si trova nell’applicazione stessa, sia client sia server, non nell’infrastruttura sottostante.
Contenuto Statico e Dinamico
I server HTTP utilizzano due meccanismi di base per soddisfare il contenuto richiesto dal client. Il primo meccanismo fornisce contenuto statico: cioè, il percorso indicato nel messaggio di richiesta corrisponde a un file sul file system locale del server. Il secondo meccanismo fornisce contenuto dinamico: cioè, il server HTTP inoltra la richiesta a un altro programma - probabilmente uno script - per costruire la risposta da diverse fonti, come database e altri file.
Anche se ci sono diversi server HTTP, tutti usano lo stesso protocollo di comunicazione HTTP e adottano più o meno le stesse convenzioni. Un’applicazione che non ha una necessità specifica può essere implementata con qualsiasi server tradizionale, come Apache o NGINX. Entrambi sono in grado di generare contenuti dinamici e fornire contenuti statici, ma ci sono sottili differenze nella configurazione di ciascuno di essi.
La posizione dei file statici da servire, per esempio, è definita in modi diversi in Apache e NGINX. La convenzione è di tenere questi file in una directory specifica per questo scopo, con un nome associato all’host, per esempio /var/www/learning.lpi.org/
. In Apache, questo percorso è definito dalla direttiva di configurazione DocumentRoot /var/www/learning.lpi.org
, in una sezione che definisce un host virtuale. In NGINX, la direttiva usata è root /var/www/learning.lpi.org
in una sezione server
del file di configurazione.
Qualsiasi server tu scelga, i file in /var/www/learning.lpi.org/
saranno serviti via HTTP quasi allo stesso modo. Alcuni campi nell’intestazione della risposta e i loro contenuti possono variare tra i due server, ma campi come Content-Type
devono essere presenti nell’intestazione della risposta e devono essere coerenti su qualsiasi server.
Caching
HTTP è stato progettato per funzionare su qualsiasi tipo di connessione Internet, veloce o lenta. Inoltre, la maggior parte degli scambi HTTP deve attraversare molti nodi di rete a causa dell’architettura distribuita di Internet. Di conseguenza è importante adottare qualche strategia di caching dei contenuti per evitare il trasferimento ridondante di contenuti precedentemente scaricati. I trasferimenti HTTP possono funzionare con due tipi base di cache: condivisa e privata.
Una cache condivisa è usata da più di un singolo client. Per esempio, un grande fornitore di contenuti potrebbe usare cache su server geograficamente distribuiti, in modo che i client ricevano i dati dal server più vicino. Una volta che un client ha fatto una richiesta e la sua risposta è stata memorizzata in una cache condivisa, altri client che fanno la stessa richiesta nella stessa area riceveranno la risposta presente nella cache.
Una cache privata è creata dal client stesso per il suo uso esclusivo. È il tipo di cache che il browser web fa per le immagini, i file CSS, il JavaScript o il documento HTML stesso, in modo che non debbano essere scaricati di nuovo se richiesti in un prossimo futuro.
Note
|
Non tutte le richieste HTTP devono essere messe in cache. Una richiesta che utilizza il metodo POST, per esempio, implica una risposta associata esclusivamente a quella particolare richiesta, quindi il suo contenuto di risposta non dovrebbe essere riutilizzato. Per impostazione predefinita, solo le risposte alle richieste effettuate con il metodo GET vengono messe in cache. Inoltre, solo le risposte con codici di stato conclusivi come 200 (OK), 206 (contenuto parziale), 301 (spostato in modo permanente) e 404 (non trovato) sono adatte alla cache. |
Sia la strategia della cache condivisa sia quella della cache privata usano le intestazioni HTTP per controllare come il contenuto scaricato dovrebbe essere messo in cache. Per la cache privata, il client consulta l’intestazione della risposta e verifica se il contenuto nella cache locale corrisponde ancora al contenuto remoto corrente. Se è così, il client rinuncia al trasferimento del payload della risposta e usa la versione locale.
La validità della risorsa in cache può essere valutata in diversi modi. Il server può fornire una data di scadenza nell’intestazione di risposta per la prima richiesta, in modo che il client scarti la risorsa in cache alla fine del termine e la richieda nuovamente per ottenere la versione aggiornata. Tuttavia, il server non è sempre in grado di determinare la data di scadenza di una risorsa, quindi è comune usare il campo intestazione di risposta ETag
per identificare la versione della risorsa, per esempio Etag: "606adcd4-46fa"
.
Per verificare che una risorsa in cache debba essere aggiornata, il client richiede al server solo la sua intestazione di risposta. Se il campo ETag
corrisponde a quello della versione memorizzata localmente, il client riutilizza il contenuto della cache. Altrimenti, il contenuto aggiornato della risorsa viene scaricato dal server.
Le Sessioni HTTP
In un sito web convenzionale o in un’applicazione web, le funzioni che gestiscono il controllo della sessione sono basate sulle intestazioni HTTP. Il server non può assumere, per esempio, che tutte le richieste provenienti dallo stesso indirizzo IP siano dello stesso client. Il metodo più tradizionale che permette al server di associare diverse richieste a un unico client è l’uso di cookies, un tag di identificazione che viene dato al client dal server e che viene fornito nell’intestazione HTTP.
I cookie permettono al server di conservare informazioni su un client specifico, anche se la persona che lo esegue non si identifica esplicitamente. Con i cookie è possibile implementare sessioni in cui i login, i carrelli della spesa, le preferenze, ecc. vengono conservati tra diverse richieste fatte allo stesso server che li ha forniti. I cookie vengono utilizzati anche per tracciare la navigazione degli utenti, quindi è importante chiedere il consenso prima di inviarli.
Il server imposta il cookie nell’intestazione della risposta usando il campo Set-Cookie
. Il valore del campo è una coppia nome=valore
scelta per rappresentare qualche attributo associato a uno specifico client. Il server può, per esempio, creare un numero di identificazione per un client che richiede una risorsa per la prima volta e passarlo al client nell’intestazione di risposta:
HTTP/1.1 200 OK Accept-Ranges: bytes Set-Cookie: client_id=62b5b719-fcbf
Se il client permette l’uso di cookie, le nuove richieste a questo stesso server hanno il campo cookie nell’intestazione:
GET /en/ HTTP/1.1 Host: learning.lpi.org Cookie: client_id=62b5b719-fcbf
Con questo numero di identificazione, il server può recuperare definizioni specifiche per il client e generare una risposta personalizzata. È anche possibile utilizzare più di un campo Set-Cookie
per fornire diversi cookie allo stesso client. In questo modo, più di una definizione può essere conservata sul lato client.
I cookie sollevano sia problemi di privacy sia potenziali falle di sicurezza, perché c’è la possibilità che possano essere trasferiti a un altro client, che sarà identificato dal server come il client originale. I cookie utilizzati per preservare le sessioni possono dare accesso a informazioni sensibili del client originale. Pertanto, è molto importante che i client adottino meccanismi di protezione locale per evitare che i loro cookie siano estratti e riutilizzati senza autorizzazione.
Esercizi Guidati
-
Quale metodo HTTP usa il seguente messaggio di richiesta?
POST /cgi-bin/receive.cgi HTTP/1.1 Host: learning.lpi.org User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0 Accept: */* Content-Length: 27 Content-Type: application/x-www-form-urlencoded
-
Quando un server HTTP ospita molti siti web, come è in grado di identificare quello a cui è destinata una richiesta?
-
Quale parametro è fornito dalla stringa di query dell’URL
https://www.google.com/search?q=LPI
? -
Perché la seguente richiesta HTTP non è adatta al caching?
POST /cgi-bin/receive.cgi HTTP/1.1 Host: learning.lpi.org User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0 Accept: */* Content-Length: 27 Content-Type: application/x-www-form-urlencoded
Esercizi Esplorativi
-
Come potresti usare il browser web per monitorare le richieste e le risposte di una pagina HTML?
-
I server HTTP che forniscono contenuti statici di solito mappano il percorso richiesto su un file nel filesystem del server. Che cosa succede quando il percorso nella richiesta punta a una directory?
-
Il contenuto dei file inviati tramite HTTPS è protetto da crittografia, quindi non può essere letto dai computer tra il client e il server. Nonostante ciò, questi computer nel mezzo possono identificare quale risorsa il client ha richiesto al server?
Sommario
Questa lezione tratta le basi di HTTP, il principale protocollo utilizzato dalle applicazioni client per richiedere risorse ai server web. La lezione passa attraverso i seguenti concetti:
-
Messaggi di richiesta, campi di intestazione e metodi.
-
Codici di stato delle risposte.
-
Come i server HTTP generano le risposte.
-
Caratteristiche HTTP utili per il caching e la gestione delle sessioni.
Risposte agli Esercizi Guidati
-
Quale metodo HTTP usa il seguente messaggio di richiesta?
POST /cgi-bin/receive.cgi HTTP/1.1 Host: learning.lpi.org User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0 Accept: */* Content-Length: 27 Content-Type: application/x-www-form-urlencoded
Il metodo POST.
-
Quando un server HTTP ospita molti siti web, come è in grado di identificare quello a cui è destinata una richiesta?
Il campo
Host
nell’intestazione della richiesta fornisce il sito web mirato. -
Quale parametro è fornito dalla stringa di query dell’URL
https://www.google.com/search?q=LPI
?Il parametro chiamato
q
con un valore diLPI
. -
Perché la seguente richiesta HTTP non è adatta al caching?
POST /cgi-bin/receive.cgi HTTP/1.1 Host: learning.lpi.org User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0 Accept: */* Content-Length: 27 Content-Type: application/x-www-form-urlencoded
Poiché le richieste fatte con il metodo POST implicano un’operazione di scrittura sul server, non dovrebbero essere messe in cache.
Risposte agli Esercizi Esplorativi
-
Come potresti usare il browser web per monitorare le richieste e le risposte di una pagina HTML?
Tutti i browser popolari offrono strumenti di sviluppo che, tra le altre cose, possono mostrare tutte le transazioni di rete che sono state effettuate dalla pagina corrente.
-
I server HTTP che forniscono contenuti statici di solito mappano il percorso richiesto su un file nel filesystem del server. Che cosa succede quando il percorso nella richiesta punta a una directory?
Dipende da come è configurato il server. Per default, la maggior parte dei server HTTP cerca un file chiamato
index.html
(o un altro nome predefinito) in quella stessa directory e lo invia come risposta. Se il file non c’è, il server emette una risposta404 Not Found
. -
Il contenuto dei file inviati tramite HTTPS è protetto da crittografia, quindi non può essere letto dai computer tra il client e il server. Nonostante ciò, questi computer nel mezzo possono identificare quale risorsa il client ha richiesto al server?
No, perché le stesse intestazioni HTTP di richiesta e risposta sono criptate da TLS.