1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
---
title: HTTP caching
slug: Web/HTTP/Caching
translation_of: Web/HTTP/Caching
---
<div>{{HTTPSidebar}}</div>
<p class="summary">Le prestazioni di siti web e applicazioni possono essere migliorate drasticamente riutilizzando le risorse già ottenute. Le web caches riducono la latenza e il traffico di rete, diminuendo il tempo necessario per rappresentare una risorsa. Attraverso l'uso dell'HTTP caching, i siti web diventano più responsivi.</p>
<h2 id="I_diversi_tipi_di_cache">I diversi tipi di cache</h2>
<p>Il caching è una tecnica che immagazzina una copia di una risorsa data e la restituisce quando richiesta. Quando una web cache ha una risorsa richiesta in memoria, intercetta la richiesta e ritorna la sua copia invece di riscaricarla dal server originale. Così si raggiungono diversi risultati: alleggerisce il carico del server che non deve più servire tutti i client da solo, e migliora le prestazioni stando più vicina al client, ad esempio, ci mette meno tempo a restituire le risorse. Per un sito web, è una componente fondamentale nell’ottenere prestazioni elevate. D’altra parte, deve essere configurato correttamente in quanto non tutte le risorse rimangono identiche per sempre. È importante mettere in cache una risorsa solo finché non cambia.</p>
<p>Ci sono diversi tipi di cache: queste possono essere raggruppate in due principali categorie: private o condivise. Una cache condivisa è una cache che immagazzina risposte per essere utilizzate da più utenti. Una cache privata è una cache dedicata ad un singolo utente. Questa pagina tratterà per la maggior parte delle browser cache e di quelle del proxy, ma ci sono anche gateway cache, CDN, reverse proxy cache e load balancer che sono impiegati nei server web per maggiore affidabilità, prestazioni e scaling di siti web e applicazioni web.</p>
<p><img alt="What a cache provide, advantages/disadvantages of shared/private caches." src="https://mdn.mozillademos.org/files/13777/HTTPCachtType.png" style="height: 573px; width: 910px;"></p>
<h3 id="Cache_private_del_browser">Cache private del browser</h3>
<p>Una cache privata è dedicata ad un singolo utente. Potresti aver già visto “caching” nelle impostazioni del tuo browser. Una browser cache conserva tutti i documenti scaricati via http dall’utente. Questa cache è usata per rendere disponibili i documenti per la navigazione avanti o indietro, salvare, vedere come risorsa, ecc. senza inviare un'altra richiesta al server. Similmente migliora la ricerca offline di contenuti in cache.</p>
<h3 id="Cache_condivise">Cache condivise</h3>
<p>Una cache condivisa è una cache che immagazzina risposte per essere utilizzate da più di un utente. Ad esempio, un ISP o la tua compagnia potrebbero aver impostato un web proxy come parte della sua infrastruttura network locale per servire molti utenti così che risorse popolari vengono riutilizzate più volte, riducendo il traffico di rete e la latenza.</p>
<h2 id="I_soggetti_del_caching"> I soggetti del caching</h2>
<p>L'HTTP caching non è obbligatorio, ma è normalmente utile. Le HTTP caches normalmente sono limitate alle risposte a {{HTTPMethod("GET")}} e potrebbero rifiutare altri metodi. La chiave primaria della cache consiste nel metodo richiesto e nell'URI desiderato (spesso viene usato solo l'URI, in quanto solo le richieste <code>GET</code> vengono salvate nella cache).</p>
<p>Informazioni che spesso vengono salvate nella cache:</p>
<ul>
<li>Risultati ottenuti da una richiesta riuscita: una risposta {{HTTPStatus(200)}} (OK) ad una richiesta {{HTTPMethod("GET")}} contenente risorse come document HTML, immagini o file.</li>
<li>Reindirizzamenti permanenti: una risposta {{HTTPStatus(301)}} (Moved Permanently).</li>
<li>Risposte di errore: la pagina allegata ad una risposta {{HTTPStatus(404)}} (Not Found).</li>
<li>Risultati incompleti: una risposta {{HTTPStatus(206)}} (Partial Content).</li>
<li>Risposte diverse da {{HTTPMethod("GET")}} se c'è l'equivalente di una chiave.</li>
</ul>
<p>I dati inseriti possono essere composti da più risposte differenziate da una chiave secondaria se la richiesta è oggetto di scambio di contenuti. Per ulterior informazioni riguardo all'header {{HTTPHeader("Vary")}} leggi <a href="#">below</a>.</p>
<h2 id="Controllare_la_cache">Controllare la cache</h2>
<h3 id="Lheader_Cache-Control">L'header <code>Cache-Control</code></h3>
<p>L'header generico {{HTTPHeader("Cache-Control")}} HTTP/1.1 viene usato per specificare i meccanismi del caching per richieste e risposte. Questo header può essere usato per definire le caching policies attraverso le direttive proposte.</p>
<h4 id="No_caching">No caching</h4>
<p>La cache non dovrebbe salvare né le richieste né le risposte. Ogni richiesta viene mandata al server, dovendo quindi riscaricare ogni volta la risposta.</p>
<pre class="notranslate">Cache-Control: no-store
</pre>
<h4 id="Cache_but_revalidate">Cache but revalidate</h4>
<p>La cache invia chiede una validazione da parte del server prima di fornire la sua copia.</p>
<pre class="notranslate">Cache-Control: no-cache</pre>
<h4 id="Private_and_public_caches">Private and public caches</h4>
<p>La direttiva "public" indica che la risposta può essere salvata da qualsiasi cache. Questo può essere utile per salvare pagine con codici di risposta HTTP che normalmente non si potrebbero salvare.</p>
<p>Dall'altro lato, "private" indica che la risposta è legata ad un solo utente, quindi non sarà salvata in una cache condivisa. In questo caso la risposta potrebbe essere salvata da una cache privata del browser.</p>
<pre class="notranslate">Cache-Control: private
Cache-Control: public
</pre>
<h4 id="Expiration">Expiration</h4>
<p>La direttiva più importante è <code>max-age=<secondi></code>, che indica il tempo massimo (in secondi) in cui la risorsa è considerata fresca ("fresh"). Questa direttiva è relativa al tempo indicato dalla richiesta e sovrascrive l'header {{HTTPHeader("Expires")}} (se impostato). I file che non mutano (come ad esempio immagini, fogli CSS e script JavaScript) sono buoni candidati per essere salvati nella cache</p>
<p>Per ulteriori dettagli visita la sezione <a href="#Freshness">Freshness</a>.</p>
<pre class="notranslate">Cache-Control: max-age=31536000</pre>
<h4 id="Validation">Validation</h4>
<p>Quando viene usata la direttiva "<code>must-revalidate</code>" la cache deve verificare lo stato della risorsa prima di usarla, evitando le risorse scadute. Per ulteriori dettagli visita la sezione <a href="#Cache_validation">Validation</a>.</p>
<p>Cache-Control: must-revalidate</p>
<h3 id="Lheader_Pragma">L'header <code>Pragma</code></h3>
<p>{{HTTPHeader("Pragma")}} è un header HTTP/1.0. <code>Pragma: no-cache</code> corrisponde a <code>Cache-Control: no-cache</code>, forzando quindi le cache a validare le risorse prima di utilizzarle. <code>Pragma</code> non è incluso nelle risposte HTTP, quindi non può sostituire completamente l'header <code>Cache-Control</code> presente in HTTP/1.1.</p>
<p>Si dovrebbe utilizzare l'header <code>Pragma</code> solo per retrocompatibilità con le cache in HTTP/1.0, dove l'header <code>Cache-Control</code> di HTTP/1.1 non è presente.</p>
<h2 id="Freschezza">Freschezza</h2>
<p>Una volta che una risorsa è memorizzata in cache, potrebbe teoricamente essere servita dalla cache per sempre. Le cache hanno una memoria finita quindi gli oggetti sono periodicamente rimossi dalla memoria. Questo processo si chiama sfratto della cache (cache eviction). D’altra parte, alcune risorse possono essere cambiate sul server quindi la cache andrebbe aggiornata. Dato che l’HTTP è un protocollo client-server, i server non possono contattare le cache e i client quando una risorsa cambia; devono comunicare un tempo di scadenza per la risorsa. Prima di questa scadenza, la risorsa è fresca; dopo la scadenza, la risorsa è datata. Gli algoritmi di sfratto spesso prediligono risorse fresche a quelle datate. Da notare che una risorsa datata non è sfrattata o ignorata; quando la cache riceve una richiesta per una risorsa datata, la inoltra con un If-None-Match per verificare se è di fatto ancora fresca. In questo caso il server ritorna un 304 (Non Modificata) header senza inviare il body della risorsa richiesta, risparmiando banda.</p>
<p>Qui è un esempio di questo processo con una proxy cache condivisa:</p>
<p><img alt="Show how a proxy cache acts when a doc is not cache, in the cache and fresh, in the cache and stale." src="https://mdn.mozillademos.org/files/13771/HTTPStaleness.png" style="height: 910px; width: 822px;"></p>
<p>La durata della freschezza è calcolata secondo diversi header. Se l'header "<code>Cache-Control: max-age=N</code>" è presente la durata sarà pari ad N, altrimenti (come spesso accade) si controlla se è presente l'header {{HTTPHeader("Expires")}}. Se esiste, la durata equivale alla differenza tra il valore dell'header {{HTTPHeader("Date")}} e il valore dell'header {{HTTPHeader("Expires")}}.</p>
<h3 id="Controllo_euristico_della_freschezza">Controllo euristico della freschezza</h3>
<p>Se un server centrale non specifica esplicitamente la durata della freschezza (usando ad esempio gli header {{HTTPHeader("Cache-Control")}} o {{HTTPHeader("Expires")}}) potrebbe essere utilizzato un approccio euristico.</p>
<p>In questo caso si cerca l'header {{HTTPHeader("Last-Modified")}}. Se presente, la freschezza è uguale alla differenza tra il valore di ques'ultimo e il valore di <code>Date</code> divisa per 10:</p>
<pre class="notranslate">dataDiScadenza = orarioDellaRisposta + durataDellaFreschezza - tempoDiVitaCorrente
</pre>
<p>dove <code>tempoDiRisposta</code> è l'ora in cui la risposta è stata ricevuta dal browser. Per maggiori informazioni: <a href="https://tools.ietf.org/html/rfc7234#section-4.2.2">RFC 7234: Hypertext Transfer Protocol (HTTP/1.1): 4.2.2. Calculating Heuristic Freshness</a>.</p>
<h3 id="Revved_resources">Revved resources</h3>
<p>Più si usa una risorsa in cache, più reattive saranno le risposte e le performance di un sito web. Per ottimizzarle, la norma è impostare i tempi di scadenza più in là possibile nel futuro. Questo è possibile con risorse che sono regolarmente aggiornate, o spesso, ma è problematico per risorse che vengono aggiornate raramente. Sono le risorse che beneficerebbero di più dalle cache, eppure questo le rende difficili da aggiornare. È tipico delle risorse tecniche incluse e linkate da ogni pagina web: I file Javascript e CSS cambiano di rado, ma quando succede vuoi che vengano aggiornati rapidamente.</p>
<p>I web developer hanno inventato una tecnica che Steve Souders chiamò revving. File sporadicamente aggiornati sono nominati in un modo specifico: nel loro URL, solitamente nel nome del file, un numero di revisione (o versione) viene aggiunto. In questo modo ogni nuova revisione di questa risorsa viene considerata come una risorsa che non cambia e può avere un tempo di scadenza molto avanti nel futuro, di solito un anno o più. Per avere le nuove versioni, tutti i link che fanno capo a loro vanno cambiati, questa è la limitazione di questo metodo: complessità aggiuntive vengono solitamente risolti dalle tool chain usate dai web developer. Quando la risorsa che cambia di rado viene modificata, questa induce un cambiamento aggiuntivo a risorse spesso variabili. Quando vengono lette, le nuove versioni della altre vengono anch’esse lette.</p>
<p>Questa tecnica ha un vantaggio aggiuntivo: aggiornare due risorse in cache nello stesso momento preverrà situazioni in cui la risorsa vecchia viene usata in combinazione con quella nuova dell’altra. Questo è molto importante quando i siti web hanno fogli CSS o script JS che hanno dipendenze reciproche, ad esempio che dipendono l’uno sull’altro perché si riferiscono agli stessi elementi HTML.</p>
<p><img alt="How the revved cache mechanism works. With minor typo fix to grammar issue: https://github.com/mdn/sprints/issues/2618" src="https://mdn.mozillademos.org/files/17432/HTTPRevved_fix_typo.png" style="height: 897px; width: 787px;"></p>
<p>La versione di revisione aggiunta a una revved resource non ha bisogno di essere una classica stringa di revisione come 1.1.3, o un numero che aumenta monotonamente. Può essere qualsiasi cosa che impedisca le collisioni, come un hash o una data.</p>
<h2 id="Validazione_della_cache">Validazione della cache</h2>
<p>Quando una risorsa presente nella cache scade può essere validata o può essere richiesta nuovamente al server. La validazione può avvenire solo se il server ha fornito un <em>validatore forte </em>(<em>strong validator</em>) o un <em>validatore debole </em>(<em>weak validator</em>).</p>
<p>La rivalidazione comincia quando l'utente ricarica la pagina, oppure quando la risposta contenuta nella cache inculde l'header "<code>Cache-Control: must-revalidate</code>". Un altro fattore è costituito dalle impostazioni nel pannello <code>Avanzate->Cache</code>, dove è possibile forzare la validazione ogni volta che un documento viene caricato.</p>
<h3 id="ETags">ETags</h3>
<p>L'header {{HTTPHeader("ETag")}}, contenuto in una risposta, è un valore <em>opaco per lo user agent </em>(<em>op</em><em>aque-to-the-useragent</em>) che può essere usato come un validatore forte. Questo significa che uno user-agent HTTP, ad esempio un browser, non sa cosa cosa questa stringa rappresenti e non può predirne il valore. Se l'header <code>ETag</code> fosse parte di una risposta contenente una risorsa, il client può inserire {{HTTPHeader("If-None-Match")}} nell'header delle richieste future, così da validare le risorse salvate nella cache.</p>
<h3 id="Last-Modified">Last-Modified</h3>
<p>L'header {{HTTPHeader("Last-Modified")}}, contenuto in una risposta, può essere usato come un validatore debole. È considerato debole per via della sua risoluzione (un secondo). Se in una risposta è presente l'header <code>Last-Modified</code> il client può inserire {{HTTPHeader("If-Modified-Since")}} nell'header della richiesta per validare il documento salvato nella cache.</p>
<p>Quando viene fatta una richiesta di validazione il server può ignorarla e rispondere con {{HTTPStatus(200)}} <code>OK</code>, oppure può ritornare {{HTTPStatus(304)}} <code>Not Modified</code> (senza corpo) per permettere al browser di usare il contenuto della cache. In quest'ultimo caso ci possono essere anche altri header che aggiornano la data di scadenza del documento salvato nella cache.</p>
<h2 id="Variare_le_risposte">"Variare" le risposte</h2>
<p>L'header delle risposte HTTP {{HTTPHeader("Vary")}} indica gli header con cui usare una risposta salvata nella cache.</p>
<p>Quando una cache riceve una richiesta contenente l'header <code>Vary</code> non deve usare una risposta salvata nella cache, a meno che tutti gli header contenuti nel campo <code>Vary</code> corrispondano agli header contenuti nella cache.</p>
<p><img alt="The Vary header leads cache to use more HTTP headers as key for the cache." src="https://mdn.mozillademos.org/files/13769/HTTPVary.png" style="height: 817px; width: 752px;">Questa proprietà viene principalmente usata per salvare nella cache una risorsa non compressa o compressa in vari formati, per inviarla poi agli user agent a seconda delle codifiche che supportano. Per esempio, un server può impostare <code>Vary: Accept-Encoding</code> per assicurarsi che la risorsa sia salvata nella cache secondo le codifiche richieste, come <code>Accept-Encoding: gzip,deflate,sdch</code>.</p>
<pre class="notranslate">Vary: <code>Accept-Encoding</code>
</pre>
<div class="note"><strong>Nota:</strong> Usa <code>Vary</code> cautamente—può ridurre drasticamente i vantaggi del caching! Un caching server dovrebbe usare la <a href="#normalization">normalizzazione</a> per rimuovere duplicati e richieste non necessarie. Questo si verifica particolarmente quando si usa <code>Vary</code> con header che possono accettare diversi valori.</div>
<p>L'header <code>Vary</code> può tornare utile per fornire contenuti diversi a utenti mobili o desktop, o per permettere ai motori di ricerca di ottenere la versione mobile di una pagina (specificando opzionalmente che non c'è <a href="https://en.wikipedia.org/wiki/Cloaking">Cloaking</a>). Questo viene attuato con l'header <code>Vary: User-Agent</code>, dato che il valore dell'header {{HTTPHeader("User-Agent")}} è diverso tra desktop e mobile.</p>
<pre class="notranslate">Vary: User-Agent
</pre>
<h3 id="Normalizzazione">Normalizzazione</h3>
<p>Come anticipato sopra, i caching server utilizzerano le risposte salvate nella cache <em>solo</em> con le richieste i cui header (e valori annessi) corrispondono <em>esattamente </em>alle risposte salvate. Questo significa che per ogni piccola differenza verrà fatta una nuova richiesta al server centrale, che verrà poi salvata nella cache.</p>
<p>Per esempio, tutte le richieste con i seguenti header verranno richieste al server, per poi essere salvate nella cache: <code>Accept-Encoding: gzip,deflate,sdch</code>, <code>Accept-Encoding: gzip,deflate</code>, <code>Accept-Encoding: gzip</code>. Probabilmente, però, il server centrale risponderà sempre con la stessa risorsa (un file gzip)!</p>
<p>Per evitare duplicati e richieste non necessarie, i caching server dovrebbero usare la <strong>normalizzazione </strong>per pre-processare le richieste e per salvare solo i file necessari nella cache. Ad esempio, nel caso di <code>Accept-Encoding</code> si possono controllare <code>gzip</code> e gli altri tipi di compressione prima di procedere. In "pseudo codice" si può codificare come:</p>
<pre class="notranslate"><code>// Normalizza Accept-Encoding
if (req.http.Accept-Encoding) {
if (req.http.Accept-Encoding ~ "gzip") {
set req.http.Accept-Encoding = "gzip";
}
// elsif other encoding types to check
else {
unset req.http.Accept-Encoding;
}
}</code>
</pre>
<p><code>User-Agent</code> ha ancora più varianti di <code>Accept-Encoding</code>. Quindi s <code>Vary: User-Agent</code> viene utilizzato per salvare nella cache le varianti dei file per mobile/desktop si potrebbe controllare se <code>"mobile"</code> e <code>"desktop"</code> sono presenti nell'header <code>User-Agent</code>.</p>
<h2 id="Guarda_anche">Guarda anche</h2>
<ul>
<li><a href="https://tools.ietf.org/html/rfc7234">RFC 7234: Hypertext Transfer Protocol (HTTP/1.1): Caching</a></li>
<li><a href="https://www.mnot.net/cache_docs">Caching Tutorial – Mark Nottingham</a></li>
<li><a href="https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching">HTTP caching – Ilya Grigorik</a></li>
<li><a href="https://redbot.org/">RedBot</a>, a tool to check your cache-related HTTP headers.</li>
</ul>
|