Il protocollo HTTP - struttura di request e response
Come il browser parla con il server: anatomia completa del messaggio HTTP, dai metodi alla status line, dagli header al body, fino alla scomposizione dell'URI.
1. HTTP: caratteristiche fondamentali
HTTP (HyperText Transfer Protocol) è il protocollo applicativo del Web: basato su paradigma client/server, scambia messaggi testuali su TCP (porta 80, 443 per HTTPS), stateless, estensibile tramite header.
HTTP nasce per trasferire ipertesti, ma oggi trasporta qualsiasi risorsa: HTML, immagini, JSON, video, flussi streaming. Ogni interazione è una coppia richiesta-risposta: il client chiede, il server elabora e risponde, poi - nel modello originario - chiude.
Client / Server
Il client inizia sempre. Il server è in ascolto passivo, mai proattivo in HTTP/1.1 (push solo con HTTP/2).
80 e 443
Default http:// = TCP 80, https:// = TCP 443. In lab puoi usare altre porte, ma il browser le deduce dallo schema.
Testuale e leggibile
Header in ASCII leggibile umano. Perfetto per debug con curl, telnet, DevTools. Binario solo da HTTP/2 in poi sul wire, ma semantica resta.
Senza stato
Ogni request è indipendente: il server non ricorda nulla. Stato gestito sopra con cookie, sessioni, token.
Persistente / non
HTTP/1.0 chiudeva sempre. HTTP/1.1 introduce keep-alive e pipelining. HTTP/2 e 3 multiplexano tutto.
Header liberi
Puoi aggiungere campi custom X-... o standard nuovi senza rompere compatibilità. Base per API REST moderne.
All'orale: se ti chiedono "stateless", rispondi subito "ogni richiesta è a sé, il server non mantiene memoria tra richieste diverse, quindi per ricordare login usiamo cookie/sessioni". È la chiave per collegare questa lezione alla prossima su cookie.
Dire "HTTP è connection-oriented quindi tiene la connessione aperta per ricordare l'utente". No: HTTP è application stateless anche su TCP persistente. TCP mantiene la connessione, HTTP non mantiene l'applicazione.
2. Struttura generale di un messaggio HTTP
Sia request che response condividono lo stesso scheletro definito da RFC 7230:
Regola inviolabile: header e body sono separati da CRLF CRLF (riga vuota). Senza quella riga, il parser non sa dove iniziano i dati.
| Elemento | Request | Response |
|---|---|---|
| Prima riga | Metodo + URI + Versione (es. GET /index.html HTTP/1.1) | Versione + Codice + Reason (es. HTTP/1.1 200 OK) |
| Header | Informazioni sul client e cosa vuole (Host è obbligatorio in 1.1) | Info sul server e sulla risorsa (Content-Type, Server, Cache-Control) |
| Riga vuota | Separatore obbligatorio CRLF | |
| Body | Opzionale, contiene dati da inviare (form, JSON) | Opzionale ma usuale, contiene la risorsa richiesta |
3. HTTP Request – anatomia nel dettaglio
La richiesta è ciò che il browser (o curl, fetch, un'app mobile) invia al server. Analizziamo l'esempio del sorgente, arricchito:
Request-Line
METHOD SP request-target SP HTTP-Version CRLF – tre token separati da singolo spazio, terminati da CR LF ( \r\n ).
- Metodo: azione che chiediamo al server (GET, POST, HEAD, PUT, DELETE, ecc). Approfonditi nella lezione 3 del modulo.
- URI / request-target: in forma origin-form
/percorso?queryè la più comune. Può essere absolute-form o authority-form per proxy. - Versione:
HTTP/1.1domina ancora didatticamente;HTTP/2eHTTP/3hanno framing binario ma stessa semantica.
Header della richiesta – categorie
Host
In HTTP/1.1 obbligatorio. Dice al server qual è il virtual host richiesto (hosting condiviso).
Accept / Accept-*
Accept: tipo MIME, Accept-Language, Accept-Encoding. Content negotiation.
User-Agent, Referer
Chi fa la richiesta e da dove viene. Utile per statistiche e adattamento.
Connection, Cache
Connection: keep-alive / close, Cache-Control, If-Modified-Since per cache.
Content-Type / Length
Presenti se c'è body: descrivono tipo e lunghezza dati in POST/PUT.
Cookie, Authorization
Per superare stateless: inviano stato salvato lato client (approfonditi in Lezione 5).
Apri il registro elettronico e fai login. Con F12 → Network vedi:
POST /api/login HTTP/1.1 con body {"username":"mario.rossi","password":"***"} e header Content-Type: application/json e Content-Length: 45. Senza quegli header il server non saprebbe come leggere il body.
Dimenticare la riga vuota tra header e body, o mettere spazi prima dei due punti in Host : valore. Sintassi corretta: Nome:SP valore CRLF. Uno spazio prima dei : = 400 Bad Request su molti server.
4. HTTP Response – come risponde il server
Struttura speculare, ma la prima riga cambia radicalmente significato: comunica l'esito.
Benvenuti alla lezione sul protocollo HTTP!
Status-Line
HTTP-Version SP Status-Code SP Reason-Phrase CRLF. Il codice a 3 cifre è quello che il programma deve guardare; la reason è umana.
2xx Successo (200 OK, 201 Created, 204 No Content) · 3xx Redirect (301 Moved, 302 Found, 304 Not Modified) · 4xx Errore client (400 Bad Request, 401 Unauthorized, 404 Not Found) · 5xx Errore server (500 Internal Server Error, 502 Bad Gateway).
Header della risposta – cosa guardare
| Header | Ruolo | Esempio |
|---|---|---|
| Date | Quando è stata generata | Sat, 28 Nov 2021 04:33:04 GMT |
| Server | Software server (spesso omesso per sicurezza) | Apache/2.4, nginx, cloudflare |
| Content-Type | Tipo MIME del body – fondamentale per il browser | text/html; charset=UTF-8, application/json |
| Content-Length / Transfer-Encoding | Come capire fine body | 1234 oppure chunked |
| Cache-Control / Expires | Gestione cache | max-age=3600, public |
| Set-Cookie | Impone cookie al client | sessionId=abc123; HttpOnly; Secure |
| Location | Dove redirigere (con 3xx) | https://nuovo.example.com/ |
Se Content-Type è sbagliato il browser scarica file invece di renderizzare. Esempio classico all'Esame di Stato: API che risponde JSON ma manda text/html → fetch fallisce. Sempre impostare Content-Type corretto lato server.
5. URI / URL – identificatore universale delle risorse
URI = Uniform Resource Identifier. URL e URN sono sottoinsiemi di URI. Ogni URI ha una sintassi gerarchica: scheme "://" authority path ["?" query] ["#" fragment]
Nel contesto HTTP, l'URI identifica cosa chiediamo. La forma più usata è origin-form: solo path + query, mentre schema e host stanno in Host header.
| Componente | Obbligatorio? | Ruolo in HTTP |
|---|---|---|
| Scheme | Negli URL sì | Definisce protocollo e porta default (http→80, https→443, ftp→21) |
| Authority (host:porta) | Sì | Chi contattare; risolto via DNS; in richiesta origin-form sta in header Host |
| Path | Sì, almeno / | Identifica risorsa gerarchica sul server. / = root |
| Query | No | Parametri non gerarchici: ?q=reti&page=2. Sempre URL-encoded |
| Fragment | No | Identifica sezione nella pagina. Consumato solo dal browser, non inviato sulla rete |
https://registro.itis.edu/api/studenti/5A?ordina=cognome&formato=json#top
– scheme https (TLS), authority registro.itis.edu, path /api/studenti/5A, query ordina + formato, fragment #top usato dalla pagina per scrollare. Se apri DevTools, vedrai che in request-line il browser manda solo /api/studenti/5A?ordina=cognome&formato=json HTTP/1.1.
Alla maturità chiedono spesso: "Fragment viene inviato al server?". Risposta: NO, mai. È client-side. Lo stesso vale per esame: se vogliono passare dati al server devono stare in path o query, non in #fragment.
6. Lettura pratica con DevTools e Wireshark
Ora che conosci la teoria, impariamo a vedere i pacchetti veri. Due strumenti indispensabili.
DevTools → Network
F12 → Network → ricarica pagina → clic su richiesta → tab Headers/Raw. Vedi request e response esatti.
curl -v
curl -v https://httpbin.org/get mostra con > request e < response headers. Perfetto per verifica.
Wireshark
Filtro http o http2. Tasto destro → Follow → HTTP Stream per vedere messaggio completo ricostruito.
Con httpbin.org se usi http:// invece di https:// molti browser forzano redirect 301 → 308. Se non vedi il tuo body, controlla la catena di redirect in Network (tab Status). Disattiva cache con flag "Disable cache".
7. Verifica / Esercizio in classe
🔬 Attività - 30 minuti (individuale + coppia)
Usa Chrome DevTools su profgiagnotti.altervista.org oppure httpbin.org. Rispondi sul quaderno, poi confronta con compagno.
- Dati questi messaggi, individua errori:
GET /index.html HTTP/1.1
Host : www.example.com
Accept:text/html
Quali violazioni RFC 7230 trovi? Riscrivi correttamente con CRLF. - Questa request:
GET https://example.com/api?user=marco rossi&id=10#sezione HTTP/1.1contiene spazi non codificati e fragment. Spiega cosa viene realmente inviato sul filo e cosa sistemeresti per codifica URL. - Data la response:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 18
{"ok":true}
È valida? Manca la riga vuota? Spiega anche differenza tra Content-Length e Transfer-Encoding chunked. - Cattura reale: apri
https://httpbin.org/get?classe=5A&materia=Sistemi e Reti. Copia request headers completi. Il server riceveSistemi e Reticon spazio o encoded? Trova%20o+. - Stateless: se HTTP non ricorda nulla, come fa il registro elettronico a tenerti loggato dopo login? Collega a Set-Cookie/Cookie e anticipa Lezione 5.
1) Errori: spazio prima di : in Host : → non valido (token non può contenere OWS prima di :). Mancano CRLF e riga vuota finale. Corretto:
GET /index.html HTTP/1.1\r\nHost: www.example.com\r\nAccept: text/html\r\n\r\n
2) Origin-form non deve contenere scheme/host. Forma corretta per proxy o server: GET /api?user=marco%20rossi&id=10 HTTP/1.1 + Host: example.com. Fragment #sezione non va mai inviato. Spazio va codificato %20 (path) o +/%20 (query). Qui marco rossi va → marco%20rossi.
3) Sì, è valida se tra header e body c'è riga vuota (anche se non mostrata con spazio). Content-Length dice esatto numero byte body (utile se conosci). Chunked invece invia in pezzi esadecimali + CRLF, utile quando generi al volo e non conosci lunghezza a priori (streaming). Non usarli insieme in HTTP/1.1.
4) httpbin mostrerà args: {"classe":"5A","materia":"Sistemi e Reti"} decodificato ma raw URL richiesto contiene materia=Sistemi%20e%20Reti o +. Verifica in DevTools → tab Payload/Query String → View URL-encoded. Browser codifica automaticamente spazi in query come %20 (standard URI).
5) Dopo login server risponde con Set-Cookie: PHPSESSID=abc123; HttpOnly; Secure. Il browser salva cookie e lo rimanda ad ogni successiva request in header Cookie: PHPSESSID=abc123. Così server ricostruisce sessione su storage server-side pur essendo HTTP stateless. Approfondiamo in Lezione 5 con cookie, sessioni, token JWT.
8. Riepilogo e concetti chiave
Nome: valore.📚 Prossimo passo - Codici di stato, cookie, sessioni ed evoluzione HTTP
Ora sai leggere un messaggio HTTP byte per byte. Nella prossima lezione daremo significato ai codici 200, 301, 404, 500, vedremo come HTTP diventa stateful con cookie e sessioni e come HTTP/2 e HTTP/3 cambiano il trasporto mantenendo la stessa semantica. Preparati con DevTools aperto.
