Chunked Transfer è un meccanismo del protocollo HTTP in cui il server trasmette il corpo della risposta in frammenti separati (blocchi) senza specificare in anticipo la dimensione totale dei dati. Ogni blocco contiene la propria dimensione in formato esadecimale e dati della lunghezza specificata, terminando con un blocco finale di dimensione zero. Secondo MDN Web Docs, 2025, Transfer-Encoding: chunked viene attivato automaticamente dal server quando la dimensione della risposta è sconosciuta in anticipo — ad esempio, durante la generazione di contenuti al volo o la trasmissione di dati in streaming.
Punti chiave
Chunked Transfer è un meccanismo HTTP definito nella specifica HTTP/1.1 (RFC 7230, sezione 4.1) che consente al server di inviare il corpo della risposta in parti senza specificare il Content-Length totale. Invece di calcolare la dimensione della risposta prima dell'invio, il server inizia la trasmissione immediatamente, inviando frammenti di dati non appena sono pronti. Ogni frammento è accompagnato dalla propria intestazione di dimensione, consentendo al client di assemblare la risposta dai pezzi.
Il meccanismo è attivato dall'intestazione Transfer-Encoding: chunked. Quando il client vede questa intestazione nella risposta, sa che il corpo verrà trasmesso a blocchi e deve leggere la risposta in un ciclo: leggere la dimensione del blocco, poi leggere i dati della dimensione specificata, poi ripetere. Il processo termina quando viene incontrato un blocco di dimensione zero. Chunked Transfer è una parte obbligatoria di HTTP/1.1, supportata da tutti i server web moderni e client HTTP.
La ragione principale per usare chunked transfer è la generazione dinamica di contenuti. Quando il server genera una risposta basata su una query del database, un'API esterna o un calcolo lungo, non può conoscere in anticipo la dimensione del risultato. Invece di bufferizzare l'intera risposta in memoria (rischioso per grandi volumi), il server attiva Transfer-Encoding: chunked e invia i dati non appena sono disponibili. Questo è particolarmente importante per server con memoria limitata e per risposte la cui dimensione può essere molto grande — da 100 MB in su.
In HTTP/2, il meccanismo chunked transfer come tale non esiste poiché il protocollo utilizza il multiplexing dei flussi a livello di frame. In HTTP/2, i dati di qualsiasi dimensione vengono trasmessi in frame DATA e la dimensione del corpo della risposta non deve essere dichiarata in anticipo — un flusso può essere chiuso in qualsiasi momento. I server moderni convertono automaticamente le risposte chunked HTTP/1.1 in trasmissione streaming equivalente durante il proxy verso un upstream HTTP/2. Chunked Transfer rimane rilevante per le connessioni HTTP/1.1.
Quando il server decide di utilizzare Chunked Transfer, non calcola Content-Length ma invia l'intestazione Transfer-Encoding: chunked. Il corpo della risposta viene quindi formato come una sequenza di blocchi. Ogni blocco inizia con una riga contenente la dimensione del blocco in formato esadecimale (senza il prefisso 0x), seguita da CRLF ( ). Poi vengono i dati del blocco della dimensione specificata, che terminano con CRLF. L'ultimo blocco ha dimensione 0, dopo il quale possono seguire intestazioni trailer.
La dimensione esadecimale consente di trasmettere blocchi di qualsiasi dimensione da 1 byte a un volume teoricamente illimitato. In pratica, la dimensione del blocco è scelta dal server: i valori tipici sono 4 KB, 8 KB o 16 KB. La dimensione ottimale del blocco dovrebbe essere un multiplo della dimensione del segmento TCP (solitamente 1460 byte per Ethernet) per minimizzare la frammentazione a livello di trasporto. Nginx utilizza blocchi da 4 KB per impostazione predefinita, Apache blocchi da 8 KB.
Un client che riceve Transfer-Encoding: chunked deve leggere la risposta blocco per blocco fino al blocco zero di terminazione. Se il client non supporta chunked transfer, il server non può utilizzare questa modalità. In pratica, tutti i client HTTP moderni — browser, OkHttp, URLSession, curl — supportano completamente le risposte chunked. La lettura in streaming consente al client di iniziare l'elaborazione dei dati prima di ricevere la risposta completa, fondamentale per le prestazioni.
| Elemento del blocco | Formato | Esempio |
|---|---|---|
| Dimensione del blocco | HEX + CRLF | 1000 |
| Dati del blocco | [dimensione byte] + CRLF | [4096 byte di dati] |
| Blocco di terminazione | 0 | 0 |
| Trailer (opzionale) | Intestazioni + CRLF | Expires: Wed, 21 Oct 2025 |
Chunked Transfer supporta le intestazioni trailer — intestazioni HTTP aggiuntive che vengono trasmesse dopo l'ultimo blocco. Questo è utile per metadati che diventano noti solo dopo il completamento della generazione della risposta: ad esempio, Content-MD5 o X-Compression-Ratio. Le intestazioni trailer devono essere dichiarate nell'intestazione Trailer: Trailer: Content-MD5, X-Compression-Ratio. In pratica, i trailer sono usati raramente — la maggior parte dei server non li include nelle risposte.
Una risposta chunked ha una struttura rigorosamente definita che il client deve analizzare correttamente. Consideriamo un esempio completo di una risposta HTTP con Transfer-Encoding: chunked. Dopo le intestazioni e una riga vuota, inizia il corpo della risposta. La struttura del corpo è una sequenza di: dimensione_blocco dati dimensione_blocco dati ... fino a 0 . Ogni dimensione viene trasmessa in notazione esadecimale usando caratteri ASCII.
Esempio di risposta del server con Chunked Transfer:
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
7
Hello
6
World!
0
In questo esempio, il server trasmette la stringa “Hello World!” in due blocchi. Il primo blocco è di 7 byte e contiene “Hello ”, il secondo è di 6 byte e contiene “World!”. Il client raccoglie i dati da entrambi i blocchi e ottiene la stringa completa. Importante: la dimensione del blocco include solo i dati, non i separatori CRLF dei blocchi stessi. Il blocco vuoto di terminazione (0 ) notifica al client che la trasmissione è completata.
import java.net.HttpURLConnection
import java.io.BufferedReader
import java.io.InputStreamReader
fun readChunkedResponse() {
val url = java.net.URL("https://stream.example.com/data")
val connection = url.openConnection() as HttpURLConnection
val reader = BufferedReader(
InputStreamReader(connection.inputStream)
)
var line: String?
while (reader.readLine().also { line = it } != null) {
println("Blocco: $line")
}
reader.close()
}
OkHttp astrae completamente lo sviluppatore dai dettagli di Chunked Transfer. Quando riceve una risposta con Transfer-Encoding: chunked, OkHttp raccoglie automaticamente i blocchi e fornisce allo sviluppatore il corpo completo della risposta tramite response.body?.string(). Per l'elaborazione in streaming, viene utilizzato response.body?.source(), che restituisce un BufferedSource e consente di leggere i dati man mano che arrivano. Lo sviluppatore non deve analizzare manualmente le dimensioni hex e CRLF — la libreria lo fa automaticamente.
Content-Length e Transfer-Encoding: chunked sono due modi mutuamente esclusivi per specificare la dimensione del corpo di un messaggio HTTP. Content-Length è un'intestazione che contiene la dimensione esatta del corpo in byte. È obbligatoria per le risposte la cui dimensione è nota in anticipo e per le richieste con corpo (POST, PUT). Content-Length consente al client di allocare un buffer della dimensione richiesta in anticipo e verificare che tutti i dati siano stati ricevuti.
Chunked Transfer viene utilizzato quando la dimensione del corpo non è nota in anticipo. Ciò si verifica in tre scenari principali: generazione dinamica di contenuti (ad esempio, una query al database il cui risultato non è ancora disponibile), trasmissione in streaming di file grandi (per evitare di bufferizzare l'intero file in memoria) e Server-Sent Events (SSE) per la trasmissione di eventi in tempo reale. La scelta tra Content-Length e chunked è responsabilità del server. Se il server conosce la dimensione prima dell'inizio della trasmissione, dovrebbe utilizzare Content-Length come meccanismo più semplice e prevedibile.
La specifica HTTP/1.1 vieta l'uso simultaneo di Content-Length e Transfer-Encoding: chunked. Se il server invia entrambe le intestazioni, il client deve ignorare Content-Length e elaborare la risposta come chunked. La priorità di Transfer-Encoding su Content-Length è stabilita nella RFC 7230 per i casi in cui un server proxy modifica il corpo della risposta e non può preservare il Content-Length originale. Alcuni client HTTP più vecchi gestiscono questa situazione in modo errato, ma le implementazioni moderne seguono la specifica.
Esistono scenari in cui Content-Length non può essere fondamentalmente calcolata in anticipo. Report dinamici generati su richiesta con filtraggio e aggregazione — il server non conosce il volume dei dati fino al completamento della query del database. Video in streaming trasmesso da una telecamera in tempo reale — la dimensione è infinita. SSE e long polling per le notifiche — la risposta può durare indefinitamente. In tutti questi casi, Chunked Transfer è l'unico meccanismo corretto.
Chunked Transfer è alla base di molte tecnologie di streaming sul web. La più nota è Server-Sent Events (SSE), dove il server invia eventi al client attraverso una singola connessione HTTP con Transfer-Encoding: chunked. SSE utilizza un formato di testo speciale (data: messaggio ), ma il livello di trasporto è il normale chunked transfer. Il browser riceve gli eventi non appena il server li invia, senza attendere il completamento della risposta.
Lo streaming audio e video si basa anch'esso su Chunked Transfer. I server multimediali come Nginx RTMP e Wowza Streaming Engine inviano dati multimediali in blocchi via HTTP. Il player lato client avvia la riproduzione non appena riceve il primo blocco, senza attendere il caricamento completo del file. Ciò riduce il tempo fino al primo fotogramma da decine di secondi a 1-2 secondi. YouTube e Netflix utilizzano esattamente questo approccio per i loro flussi HTTP.
Nello sviluppo mobile, Chunked Transfer viene utilizzato per trasferire grandi volumi di dati senza caricare l'intera risposta in memoria. Durante il caricamento di immagini tramite Coil o Glide su Android, le librerie leggono i dati in streaming blocco per blocco e decodificano gradualmente l'immagine. Ciò consente di visualizzare immagini grandi (10+ MB) senza OutOfMemoryError. OkHttp supporta la lettura in streaming tramite response.body?.byteStream(), che restituisce un InputStream che legge i dati blocco per blocco.
gRPC utilizza HTTP/2, dove lo streaming è integrato a livello di protocollo e non richiede un meccanismo chunked separato. I server GraphQL che funzionano su HTTP/1.1 possono utilizzare Chunked Transfer per lo streaming dei risultati delle sottoscrizioni. Apollo Server e Hasura inviano risposte chunked per le sottoscrizioni GraphQL, trasmettendo gli eventi man mano che si verificano. Il client riceve aggiornamenti in tempo reale senza necessità di polling.
Chunked Transfer fornisce importanti vantaggi per le applicazioni web. Invio immediato dei dati — il server non bufferizza la risposta prima dell'invio, riducendo la latenza fino al primo byte. Elaborazione in streaming — il client può iniziare a elaborare i dati man mano che arrivano senza attendere il download completo. Nessuna limitazione di memoria — il server non memorizza l'intera risposta in memoria, fondamentale per grandi volumi di dati. Capacità di trasmettere flussi infiniti — SSE, video in diretta, monitoraggio.
Tuttavia, Chunked Transfer ha delle limitazioni. Overhead per ogni blocco è di 6-12 byte per la dimensione + CRLF, che per molti blocchi piccoli (ad esempio, 100 byte ciascuno) può aumentare la dimensione della risposta del 10-15%. Impossibilità di specificare la dimensione esatta — il client non può allocare un buffer in anticipo o mostrare una barra di progresso. Problemi con i server proxy — alcuni proxy più vecchi non supportano chunked transfer e non possono memorizzare nella cache tali risposte. Nessun supporto per la ripresa dei download — non è possibile effettuare richieste Range per risposte chunked ricevute parzialmente.
Secondo HTTP Archive, 2025, circa il 35% di tutte le risposte HTTP utilizza Transfer-Encoding: chunked. Tra queste predominano le pagine dinamiche (60%), le risposte API (25%) e i flussi multimediali (15%). I file statici utilizzano quasi sempre Content-Length poiché la loro dimensione è nota in anticipo. La percentuale di risposte chunked sta gradualmente diminuendo con l'adozione di HTTP/2, dove lo streaming è implementato a livello di frame senza la necessità di un'intestazione Transfer-Encoding aggiuntiva.
Nello sviluppo mobile, utilizzare Chunked Transfer per scaricare file grandi (immagini, video) e per richieste API che restituiscono grandi array di dati. OkHttp supporta completamente chunked transfer senza configurazione aggiuntiva. Per i caricamenti sul server, Chunked Transfer non viene utilizzato — HTTP/1.1 non ha Transfer-Encoding per i caricamenti. Su iOS, URLSession supporta sia l'invio che la ricezione di dati chunked senza configurazione speciale. L'analisi JSON in streaming (ad esempio, tramite Jackson Streaming API o Moshi) consente di elaborare grandi array JSON man mano che arrivano in un flusso chunked.
Domande frequenti
Il server attiva Chunked Transfer automaticamente quando la dimensione della risposta è sconosciuta. Nginx aggiunge Transfer-Encoding: chunked se Content-Length non è impostato. In Spring Boot, StreamingResponseBody e SseEmitter utilizzano automaticamente chunked transfer. In Node.js Express, la risposta diventa chunked se si chiama res.write() e res.end() senza Content-Length.
No, la specifica HTTP/1.1 vieta l'uso simultaneo di Content-Length e Transfer-Encoding: chunked. Se il server invia entrambe le intestazioni, il client deve ignorare Content-Length ed elaborare la risposta come chunked. Questa regola è stabilita nella RFC 7230 per la compatibilità con i server proxy che possono modificare il corpo della risposta.
La dimensione ottimale del blocco dipende dallo scenario. Per le pagine web ordinarie — 4-8 KB. Per lo streaming video — 16-64 KB. Per SSE — blocchi minimi di 1-2 KB per ridurre la latenza. La dimensione del blocco dovrebbe essere un multiplo della dimensione del segmento TCP (1460 byte per Ethernet) per minimizzare la frammentazione a livello di trasporto.
I server proxy moderni (Nginx, HAProxy, Envoy) supportano Chunked Transfer. Il proxy può inoltrare i blocchi senza bufferizzazione (streaming) o bufferizzare l'intera risposta e reinviarla con Content-Length. I proxy più vecchi possono bufferizzare la risposta chunked fino al completamento, aumentando la latenza. HTTP/2 risolve questo problema a livello di protocollo.
È la stessa cosa. Chunked Transfer è il nome completo del meccanismo dalla specifica HTTP/1.1. HTTP chunked encoding è lo stesso, a volte utilizzato nella documentazione delle librerie. Transfer-Encoding: chunked è l'intestazione che attiva questa modalità. Tutti e tre i termini descrivono lo stesso meccanismo di trasmissione dei dati in parti.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche