Il protocollo HTTP - struttura di request e response | Sistemi e Reti | Prof. Giagnotti
Anno 5 · Modulo 1 · Lezione 4
A cura di Prof. Giagnotti · Sistemi e Reti

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.

📚 Anno 5 · Modulo 1 ⏱ 25 min lettura 🎯 Livello: Fondamentale per maturità 🧪 Lab: Wireshark
// Obiettivi di apprendimento
✓Elencare le caratteristiche chiave del protocollo HTTP: paradigma client/server, porta 80/443, formato testuale, stateless e ruolo delle connessioni persistenti.
✓Analizzare byte per byte una HTTP Request: request line (metodo + URI + versione), header obbligatori/opzionali, riga vuota e body opzionale.
✓Analizzare una HTTP Response: status line (versione + codice + reason), header di controllo/cache/server e body con la risorsa.
✓Decomporre un URI/URL completo in schema, authority, path, query e fragment e spiegarne il ruolo nel routing HTTP.
✓Saper leggere una cattura reale con DevTools o Wireshark e riconoscere errori comuni (Host mancante, spaziatura header, CRLF).

1. HTTP: caratteristiche fondamentali

📌 Definizione da ricordare

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.

01 · PARADIGMA

Client / Server

Il client inizia sempre. Il server è in ascolto passivo, mai proattivo in HTTP/1.1 (push solo con HTTP/2).

02 · PORTE

80 e 443

Default http:// = TCP 80, https:// = TCP 443. In lab puoi usare altre porte, ma il browser le deduce dallo schema.

03 · FORMATO

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.

04 · STATELESS

Senza stato

Ogni request è indipendente: il server non ricorda nulla. Stato gestito sopra con cookie, sessioni, token.

05 · CONNESSIONE

Persistente / non

HTTP/1.0 chiudeva sempre. HTTP/1.1 introduce keep-alive e pipelining. HTTP/2 e 3 multiplexano tutto.

06 · ESTENSIBILE

Header liberi

Puoi aggiungere campi custom X-... o standard nuovi senza rompere compatibilità. Base per API REST moderne.

💬 Tip del docente

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.

⚠️ Errore comune

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:

HTTP REQUEST Request-Line: METHOD SP URI SP VERSION CRLF Headers (0..n)Host: www.example.comUser-Agent: Mozilla/5.0 ...Accept: text/html CRLF (riga vuota obbligatoria) Body opzionale(solo con POST/PUT/PATCH, dati form, JSON) HTTP RESPONSE Status-Line: VERSION SP CODE SP REASON CRLF HeadersContent-Type: text/htmlContent-Length: 1234Set-Cookie: id=abc CRLF (riga vuota obbligatoria) Body (risorsa)<html>... risorsa richiesta ...</html>

Regola inviolabile: header e body sono separati da CRLF CRLF (riga vuota). Senza quella riga, il parser non sa dove iniziano i dati.

ElementoRequestResponse
Prima rigaMetodo + URI + Versione (es. GET /index.html HTTP/1.1)Versione + Codice + Reason (es. HTTP/1.1 200 OK)
HeaderInformazioni sul client e cosa vuole (Host è obbligatorio in 1.1)Info sul server e sulla risorsa (Content-Type, Server, Cache-Control)
Riga vuotaSeparatore obbligatorio CRLF
BodyOpzionale, 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:

HTTP · RAW REQUEST
GET /en/html/index.html HTTP/1.1 Host: www.profgiagnotti.it User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate, br Connection: keep-alive

Request-Line

📌 Struttura 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.1 domina ancora didatticamente; HTTP/2 e HTTP/3 hanno framing binario ma stessa semantica.

Header della richiesta – categorie

OBBLIGATORIO

Host

In HTTP/1.1 obbligatorio. Dice al server qual è il virtual host richiesto (hosting condiviso).

NEGOZIAZIONE

Accept / Accept-*

Accept: tipo MIME, Accept-Language, Accept-Encoding. Content negotiation.

CONTESTO

User-Agent, Referer

Chi fa la richiesta e da dove viene. Utile per statistiche e adattamento.

CONTROLLO

Connection, Cache

Connection: keep-alive / close, Cache-Control, If-Modified-Since per cache.

BODY INFO

Content-Type / Length

Presenti se c'è body: descrivono tipo e lunghezza dati in POST/PUT.

STATO

Cookie, Authorization

Per superare stateless: inviano stato salvato lato client (approfonditi in Lezione 5).

🎯 Esempio in classe - richiesta POST reale

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.

HTTP · POST con body JSON
POST /api/v1/studenti HTTP/1.1 Host: api.itis.local Content-Type: application/json Content-Length: 52 Authorization: Bearer eyJhbGci...{"nome":"Anna","classe":"5A","indirizzo":"Informatica"}
⚠️ Errore comune

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.

HTTP · RAW RESPONSE dal sorgente
HTTP/1.1 200 OK Transfer-Encoding: chunked Date: Sat, 28 Nov 2021 04:33:04 GMT Server: Apache/1.4 Connection: close Expires: Sat, 28 Nov 2021 05:33:04 GMT Cache-Control: max-age=3600, public Content-Type: text/htmlIl protocollo HTTP

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.

🎯 Mappa rapida codici (dettaglio completo in Lezione 5)

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

HeaderRuoloEsempio
DateQuando è stata generataSat, 28 Nov 2021 04:33:04 GMT
ServerSoftware server (spesso omesso per sicurezza)Apache/2.4, nginx, cloudflare
Content-TypeTipo MIME del body – fondamentale per il browsertext/html; charset=UTF-8, application/json
Content-Length / Transfer-EncodingCome capire fine body1234 oppure chunked
Cache-Control / ExpiresGestione cachemax-age=3600, public
Set-CookieImpone cookie al clientsessionId=abc123; HttpOnly; Secure
LocationDove redirigere (con 3xx)https://nuovo.example.com/
💬 Tip del docente

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.

HTTP · 404 con body JSON - esempio API moderna
HTTP/1.1 404 Not Found Date: Mon, 12 May 2025 10:15:30 GMT Content-Type: application/json; charset=UTF-8 Content-Length: 68 Cache-Control: no-cache{"error":"Studente non trovato","code":"STUDENT_NOT_FOUND","id":123}

5. URI / URL – identificatore universale delle risorse

📌 Definizione RFC 3986

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.

https://www.profgiagnotti.it:443/lezioni/http?anno=5&modulo=1#sez3 SCHEMEhttps AUTHORITYwww... :443 PATH/lezioni/http QUERYanno=5&modulo=1 FRAGMENT#sez3 Scheme = come comunicare | Authority = host[:port] | Path = gerarchia risorsa | Query = parametri ?key=value&... | Fragment = ancoraggio client-side (mai inviato al server)
ComponenteObbligatorio?Ruolo in HTTP
SchemeNegli 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
PathSì, almeno /Identifica risorsa gerarchica sul server. / = root
QueryNoParametri non gerarchici: ?q=reti&page=2. Sempre URL-encoded
FragmentNoIdentifica sezione nella pagina. Consumato solo dal browser, non inviato sulla rete
🎯 Esempio scolastico URI complesso

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.

💬 Tip del docente

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.

BROWSER

DevTools → Network

F12 → Network → ricarica pagina → clic su richiesta → tab Headers/Raw. Vedi request e response esatti.

CLI

curl -v

curl -v https://httpbin.org/get mostra con > request e < response headers. Perfetto per verifica.

ANALIZZATORE

Wireshark

Filtro http o http2. Tasto destro → Follow → HTTP Stream per vedere messaggio completo ricostruito.

BASH · debug HTTP
# Richiesta GET verbosa curl -v https://profgiagnotti.it/ --http1.1# Richiesta POST con header e body curl -v -X POST https://httpbin.org/post \ -H "Content-Type: application/json" \ -d '{"classe":"5A","materia":"Sistemi"}'# Mostra solo headers risposta curl -I https://www.google.com# Con netcat per inviare raw HTTP manuale (per capire CRLF) printf "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n" | nc example.com 80
⚠️ Errore di laboratorio

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.

  1. 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.
  2. Questa request: GET https://example.com/api?user=marco rossi&id=10#sezione HTTP/1.1 contiene spazi non codificati e fragment. Spiega cosa viene realmente inviato sul filo e cosa sistemeresti per codifica URL.
  3. 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.
  4. Cattura reale: apri https://httpbin.org/get?classe=5A&materia=Sistemi e Reti. Copia request headers completi. Il server riceve Sistemi e Reti con spazio o encoded? Trova %20 o +.
  5. 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.
✅ Soluzione ragionata

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.

✓HTTP è testuale, client/server, porta 80/443, stateless: ogni coppia request/response è indipendente; stato con cookie/sessioni.
✓Request = request-line + header + CRLF + body opzionale. Host obbligatorio in HTTP/1.1. Header sintassi Nome: valore.
✓Response = status-line + header + CRLF + body. Status code decide semantica: 2xx ok, 3xx redirect, 4xx client error, 5xx server error.
✓Header chiave: Content-Type, Content-Length vs chunked, Cache-Control, Set-Cookie/Cookie, Location, Authorization.
✓URI = scheme :// authority path ?query #fragment. Fragment non inviato; path origin-form in request; query sempre percent-encoded.
✓Debug: DevTools Network, curl -v / -I, Wireshark filtro http. Controlla sempre riga vuota CRLF CRLF tra header e body.

📚 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.