I protocolli HTTP (HyperText Transfer Protocol) e HTTPS (HTTP Secure) sono tra i più importanti protocolli della rete Internet. HTTP è stato creato da Tim Berners-Lee al CERN di Ginevra (qui la versione del 1992), ed è poi stato pubblicato ufficialmente dall’IETF nell’RFC 1945 nel 1996.
Le versioni di HTTP più diffuse sono (dal più al meno diffuso):
- HTTP/2: RFC 9113
- HTTP/3: RFC 9114
- HTTP/1.1: RFC 9112
Funzionamento
Il protocollo HTTP è un protocollo basato sul paradigma client/server ed utilizza il protocollo TCP a livello di trasporto. A tale scopo sono riservate le porte 80 e 443 per server HTTP e HTTPS, rispettivamente. Spesso vengono usate porte oltre la 1024 (tipici esempi sono 8080, 8000, …), soprattutto quando non è possibile operare sulla porta 80 per motivi di sicurezza e/o privilegi (per aprire le porte da 1024 in giù, sono necessari i privilegi di amministratore).
Una comunicazione HTTP avviene secondo i seguenti passi:
- il client stabilisce una connessione TCP con il server;
- il client manda una richiesta HTTP al server;
- il server processa la richiesta e prepara una risposta;
- il server invia la risposta al client;
- la connessione viene chiusa (salvo richiesta esplicita di mantenerla attiva).
La richiesta HTTP
Ogni richiesta HTTP è formata da un comando e da un header, il comando a sua volta
contiene, solitamente, un metodo (method), un path e la versione del
protocollo. Il comando dell’esempio a destra:
- usa il metodo
GET
, - chiede il path
/
- utilizza la version
1.1
del protocollo HTTP
.
Dopo il comando, la richiesta HTTP può contenere un header composta da una
lista di coppie chiave/valore (sia la chiave che il valore sono stringhe). Nell’esempio
a destra ci sono due coppie:
- chiave
Host
valore developer.mozilla.org
, - chiave
Accept-Language
valore fr
.
La richiesta HTTP termina con due caratteri di fine righe (un fine riga è CR+LF
: carriage return
più line feed).
Attenzione
Nella versione 1.1 di HTTP, l’header deve contenere l’indicazione dell’Host
che indica
indirizzo (e porta opzionalmente) del server. In caso di mancato inserimento di questo
campo nell’header, la richiesta può essere rifiutata con un messaggio simile al seguente
HTTP/1.1 400 Bad Request: missing required Host header
Content-Type: text/plain; charset=utf-8
Connection: close
400 Bad Request: missing required Host header
Comandi
Il comando spedito nella richiesta HTTP può essere uno tra quelli definiti nel corrispondente RFC
(la lista dei comandi disponibili può variare in base alla versione del protocollo). Il comando
è indicato con una stringa (solitamente maiuscola) all’inizio della richiesta, tra i comandi più
utilizzati ci sono:
GET
richiede una risorsa (es. file) al server, la risorsa, se presente, deve essere spedita al client senza alcun effetto sullo stato del server.POST
simile a GET
viene utilizzato per spedire informazione addizionale, il tipico uso è la
spedizione dei dati inseriti un u form HTML.PUT
genera o aggiorna una risorsa presente nel serverDELETE
richiede l’eliminazione di una risorsa dal server.HEAD
richiede informazioni su una risorsa, ma non la risorsa stessa, può essere utilizzato, ad
esempio, per sapere se un file (magari di dimensioni notevoli) è stato modificato e quindi necessita
di essere ri-scaricato.
La risposta HTTP
Dopo aver decodificato (parsing) la richiesta ed eseguite le opportune operazioni
(ad esempio recuperato il file richiesto), il server costruisce una risposta HTTP che
spedisce al client utilizzando il flusso Server -> Client
della connessione TCP.
La risposta ha un formato simile alla richiesta ed è composta di uno stato, da un
header opzionale e da un corpo (body). Lo stato contiene
- la versione (version) del protocollo HTTP utilizzata,
- uno status code che indica lo stato della richiesta (vedi sotto)
- uno status message che fornisce una descrizione dello status code
Come per la richiesta, l’header contiene una lista di coppie chiave/valore al termine
della quale. Dopo l’header, il messaggio può contenere una linea vuota prima che vi
sia il corpo del messaggio (ad esempio il contenuto del file HTML) che termina con
due righe vuote.
Status code
Una volta ricevuta la richiesta nel formato descritto sopra,
il server la elabora e agisce di conseguenza. Questa elaborazione può andare a buon fine, ma
può anche fallire per vari motivi, ad esempio:
- la risorsa richiesta può essere o meno disponibile;
- il client potrebbe non avere i permessi necessari ad accedere e/o modificare
- la richiesta potrebbe avere una sintassi non corretta;
- un errore può avvenire durante l’elaborazione nel server
- …
Per indicare lo stato della richiesta, il server spedisce al client uno status code,
questi codici numerici sono composti di tre cifre decimali la prima delle quali la tipologia
di codice (alcuni codici importanti vengono riportati).
1XX
(informazioni) richiesta ricevuta ed ancora in fase di processing.2XX
(successo) richiesta ricevuta ed accettata.3XX
(redirect) Serve un ulteriore passaggio da parte del client.4XX
(client error) request con sintassi o non soddisfacibile.400
: Bad Request403
: Forbidden404
: Not Found
5XX
(server error) il server non può soddisfare la richiesta (che però è corretta)500
Internal Server Error503
Service Unavailable
Sessione HTTP
Il protocollo HTTP è un protocollo stateless nel senso che due connessione tra gli
stessi client e server, non viene ricordata dal server. Nel caso di autenticazione
(operazione estremamente frequente nel Web di oggi), ogni nuova richiesta (esempio
ogni nuova pagina) finirebbe con il richiedere le credenziali di accesso, cosa che
renderebbe inutilizzabile un sito.
Per ovviare a questo problema, le applicazioni web, che utilizzano quasi esclusivamente
il protocollo HTTP, utilizzano un meccanismo di sessione, solitamente basato su
token memorizzati nella cache le browser mediante i cosiddetti cookies.
Cookies
I cookie sono dei dati che vengono spediti da un server mediante il protocollo HTTP
e che vengono salvati dal client. Una volta memorizzati (ad esempio nel browser) ogni
volta che una richiesta viene spedita al server che ha creato il cookie, il client aggiunge
i dati alla richiesta HTTP. In questo modo il server può tracciare le richieste
provenienti da uno stesso client, cosa che non sarebbe possibile utilizzando HTTP senza
i cookie.
Scambio di cookie
I cookie vengono gestiti mediante l’header dei messaggi HTTP:
- in una risposta dal server, si usa la chiave
Set-Cookie: DATA
per impostare (salvare)
un cookie nel client; - in una richiesta dal client, si usa la chiave
Cookie: DATA
per spedire al
server un cookie salvato.
I cookie sono stringhe contenenti delle coppie nome=valore
, ad esempio il server
potrebbe inviare una risposta del tipo
HTTP/2.0 200 OK
Content-Type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
con la quale chiede al cliente di memorizzare due cookie: yummy_cookie
con valore choco
e tasty_cookie
con valore strawberry
.
Ogni successiva richiesta al server da parte del client conterrà i cookie nell’header
della richiesta, ad esempio i due cookie sopra impostati saranno rispediti con una
richiesta HTTP simile alla seguente
GET /sample_page.html HTTP/2.0
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
dove il campo Host:
dell’header sarà quello associato al server che ha precedentemente
spedito i cookie.
Durata dei cookie
La durata in un cookie può essere di due tipi
- session cookie (cookie di sessione) che vengono eliminati alla chiusura del browser e
- permanent cookie (cookie permanenti) che rimangono impostati anche dopo la chiusura del
browser, questi cookie, tuttavia, hanno una data di scadenza (expire date) che viene
impostata dal server quando viene spedito il cookie.
Per indicare la scadenza di un cookie, si imposta Expire=SCADENZA
dopo il valore del cookie,
ad esempio
Set-Cookie: id=a3fWa; Expires=Thu, 31 Oct 2021 07:28:00 GMT;
È possibile cancellare un cookie indicando una scadenza nel passato, in questo modo il client
considererà il cookie scaduto e, di conseguenza, lo eliminerà dalla propria memoria.
Attenzione
Per indicare un cookie di sessione, il server invia il cookie senza indicare la scadenza,
se un cookie viene spedito con una scadenza, allora il cookie viene gestito dal client come
un cookie permanente.
Cookie e sicurezza
Oltre ad Expire
ci sono altri valori che possono essere impostati su un cookie, molti di
questi hanno a che fare con la sicurezza.
SameSite
(possibili valori: Strict
, Lax
e None
) indica se il client accetta cookie
provenienti solo dall’host verso cui ha indirizzato la richiesta oppure se accetta anche i
cookie di terze parti (third parties cookie).HttpOnly
impedisce l’accesso al cookie mediante Javascript, in questo modo gli script
(anche di malintenzionati) non possono accedere ai cookie.Secure
impone che il cookie venga trasmesso utilizzando una connessione sicura mediante
HTTPS.
Osserva
I cookie possono contenere informazioni sensibili e sono quindi soggetti ai vari regolamenti
di protezione dei dati come, ad esempio, il GDPR europeo.
Riferimenti
Strumenti utili per debugging HTTP