13. Caching in HTTP (Memorizzazione nella Cache HTTP)
13 Caching in HTTP
HTTP è tipicamente usato per sistemi informativi distribuiti, dove le prestazioni possono essere migliorate mediante l'uso di cache di risposta. Il protocollo HTTP/1.1 include numerosi elementi volti a far funzionare la memorizzazione nella cache il meglio possibile. Poiché questi elementi sono inscindibili dagli altri aspetti del protocollo, e poiché interagiscono tra loro, è utile descrivere il progetto di base della cache di HTTP separatamente dalle descrizioni dettagliate di method, header, response code e così via.
La cache sarebbe inutile se non migliorasse sensibilmente le prestazioni. L'obiettivo della cache in HTTP/1.1 è eliminare la necessità di inviare request in molti casi, ed eliminare la necessità di inviare risposte complete in molti altri casi. Il primo riduce il numero di andate e ritorni in rete richiesti da molte operazioni; a questo scopo usiamo un meccanismo di "expiration" (vedere la sezione 13.2). Il secondo riduce i requisiti di larghezza di banda della rete; a questo scopo usiamo un meccanismo di "validation" (vedere la sezione 13.3).
I requisiti di prestazioni, disponibilità e funzionamento disconnesso ci impongono di poter allentare l'obiettivo della trasparenza semantica. Il protocollo HTTP/1.1 consente a server di origine, cache e client di ridurre esplicitamente la trasparenza quando necessario. Tuttavia, poiché il funzionamento non trasparente può confondere gli utenti non esperti e può essere incompatibile con certe applicazioni server (come quelle per l'ordinazione di merci), il protocollo richiede che la trasparenza sia allentata:
- solo mediante una richiesta esplicita a livello di protocollo, quando è allentata dal client o dal server di origine
- solo con un avviso esplicito all'utente finale, quando è allentata dalla cache o dal client
Pertanto, il protocollo HTTP/1.1 fornisce questi importanti elementi:
1. Funzionalità di protocollo che forniscono piena trasparenza semantica quando questa è richiesta da tutte le parti.
2. Funzionalità di protocollo che consentono a un server di origine o a un user agent di richiedere e controllare esplicitamente un funzionamento non trasparente.
3. Funzionalità di protocollo che consentono a una cache di allegare avvisi alle risposte che non preservano l'approssimazione richiesta di trasparenza semantica.
Un principio di base è che i client devono poter rilevare qualsiasi potenziale allentamento della trasparenza semantica.
Note: chi implementa il server, la cache o il client può trovarsi di fronte a decisioni progettuali non discusse esplicitamente in questa specifica. Se una decisione può influire sulla trasparenza semantica, l'implementatore dovrebbe propendere per il mantenimento della trasparenza, a meno che un'analisi accurata e completa non mostri vantaggi significativi nel romperla.
13.1.1 Cache Correctness (Correttezza della Cache)
Una cache corretta deve (MUST) rispondere a una richiesta con la risposta più aggiornata detenuta dalla cache che sia appropriata alla richiesta (vedere le sezioni 13.2.5, 13.2.6 e 13.12) e che soddisfi una delle seguenti condizioni:
1. È stata verificata quanto all'equivalenza con ciò che il server di origine avrebbe restituito, rivalidando la risposta presso il server di origine (sezione 13.3);
2. È "abbastanza fresca" (vedere la sezione 13.2). Nel caso predefinito, ciò significa che soddisfa il requisito di freschezza meno restrittivo tra client, server di origine e cache (vedere la sezione 14.9); se il server di origine lo specifica, è il requisito di freschezza del solo server di origine.
Se una risposta memorizzata non è "abbastanza fresca" secondo il requisito di freschezza più restrittivo sia del client sia del server di origine, in circostanze attentamente valutate la cache può (MAY) comunque restituire la risposta con l'intestazione Warning appropriata (vedere le sezioni 13.1.5 e 14.46), a meno che tale risposta sia vietata (ad esempio da una cache-directive "no-store" o da una cache-request-directive "no-cache"; vedere la sezione 14.9).
3. È un messaggio di risposta appropriato 304 (Not Modified), 305 (Proxy Redirect) o di errore (4xx o 5xx).
Se la cache non riesce a comunicare con il server di origine, una cache corretta dovrebbe (SHOULD) rispondere come sopra se la risposta può essere servita correttamente dalla cache; in caso contrario deve (MUST) restituire un errore o un avviso che indichi un guasto di comunicazione.
Se una cache riceve una risposta (una risposta intera oppure una risposta 304 (Not Modified)) che normalmente inoltrerebbe al client richiedente, e la risposta ricevuta non è più fresca, la cache dovrebbe (SHOULD) inoltrarla al client richiedente senza aggiungere un nuovo Warning (ma senza rimuovere alcuna intestazione Warning esistente). Una cache non dovrebbe (SHOULD NOT) tentare di rivalidare una risposta solo perché tale risposta è diventata obsoleta in transito; ciò potrebbe portare a un ciclo infinito. Uno user agent che riceve una risposta obsoleta senza Warning può (MAY) mostrare all'utente un'indicazione di avviso.
13.1.2 Warnings (Avvisi)
Ogni volta che una cache restituisce una risposta che non è né di prima mano né "abbastanza fresca" (nel senso della condizione 2 della sezione 13.1.1), deve (MUST) allegare un avviso in tal senso, usando un'intestazione generale Warning. L'intestazione Warning e gli avvisi attualmente definiti sono descritti nella sezione 14.46. L'avviso consente ai client di intraprendere l'azione appropriata.
Gli avvisi possono (MAY) essere usati per altri scopi, sia legati alla cache sia di altro tipo. L'uso di un avviso, anziché di un codice di stato di errore, distingue queste risposte dai veri guasti.
Agli avvisi sono assegnati codici di avviso di tre cifre. La prima cifra indica se il Warning deve (MUST) o non deve (MUST NOT) essere eliminato da una voce di cache memorizzata dopo una rivalidazione riuscita:
1xx Avvisi che descrivono la freschezza o lo stato di rivalidazione della risposta, e che quindi devono (MUST) essere eliminati dopo una rivalidazione riuscita. I warn-code 1xx possono (MAY) essere generati da una cache solo quando valida una voce memorizzata nella cache. Non devono (MUST NOT) essere generati dai client.
2xx Avvisi che descrivono qualche aspetto del corpo dell'entità o delle intestazioni dell'entità che non viene corretto da una rivalidazione (ad esempio una compressione con perdita dei corpi delle entità) e che non devono (MUST NOT) essere eliminati dopo una rivalidazione riuscita.
Per le definizioni dei codici stessi, vedere la sezione 14.46.
Le cache HTTP/1.0 memorizzeranno tutti i Warning nelle risposte, senza eliminare quelli della prima categoria. I Warning nelle risposte che vengono passate a cache HTTP/1.0 portano un campo warning-date aggiuntivo, che impedisce a un futuro destinatario HTTP/1.1 di credere a un Warning memorizzato erroneamente.
Gli avvisi portano anche un testo di avviso. Il testo può (MAY) essere in qualsiasi lingua naturale appropriata (magari in base alle intestazioni Accept del client) e includere un'indicazione OPTIONAL di quale set di caratteri sia usato.
Più avvisi possono (MAY) essere allegati a una risposta (dal server di origine o da una cache), compresi più avvisi con lo stesso numero di codice. Ad esempio, un server potrebbe fornire lo stesso avviso con testi sia in inglese sia in basco.
Quando più avvisi sono allegati a una risposta, potrebbe non essere pratico o ragionevole mostrarli tutti all'utente. Questa versione di HTTP non specifica regole di priorità rigide per decidere quali avvisi mostrare e in quale ordine, ma suggerisce alcune euristiche.
13.1.3 Cache-control Mechanisms (Meccanismi di Controllo della Cache)
I meccanismi di base della cache in HTTP/1.1 (tempi di scadenza e validatori specificati dal server) sono direttive implicite alle cache. In alcuni casi, un server o un client può aver bisogno di fornire direttive esplicite alle cache HTTP. A questo scopo usiamo l'intestazione Cache-Control.
L'intestazione Cache-Control consente a un client o a un server di trasmettere varie direttive in richieste o risposte. Queste direttive tipicamente prevalgono sugli algoritmi di cache predefiniti. Come regola generale, se vi è un apparente conflitto tra valori di intestazione, si applica l'interpretazione più restrittiva (cioè quella che più probabilmente preserva la trasparenza semantica). Tuttavia, in alcuni casi le direttive cache-control sono esplicitamente specificate come indebolenti l'approssimazione della trasparenza semantica (ad esempio "max-stale" o "public").
Le direttive cache-control sono descritte in dettaglio nella sezione 14.9.
13.1.4 Explicit User Agent Warnings (Avvisi Espliciti dell'User Agent)
Molti user agent consentono agli utenti di prevalere sui meccanismi di cache di base. Ad esempio, lo user agent potrebbe consentire all'utente di specificare che le entità memorizzate nella cache (anche quelle esplicitamente obsolete) non vengano mai rivalidate. Oppure lo user agent potrebbe aggiungere abitualmente "Cache-Control: max-stale=3600" a ogni richiesta. Lo user agent non dovrebbe (SHOULD NOT) adottare come impostazione predefinita né un comportamento non trasparente né un comportamento che produca una cache anormalmente inefficace, ma può (MAY) essere configurato esplicitamente in tal senso da un'azione esplicita dell'utente.
Se l'utente ha prevalso sui meccanismi di cache di base, lo user agent dovrebbe (SHOULD) indicare esplicitamente all'utente ogni volta che ciò comporta la visualizzazione di informazioni che potrebbero non soddisfare i requisiti di trasparenza del server (in particolare, se l'entità visualizzata è notoriamente obsoleta). Poiché il protocollo normalmente consente allo user agent di determinare se le risposte sono obsolete o no, questa indicazione va mostrata solo quando ciò accade effettivamente. L'indicazione non deve essere una finestra di dialogo; potrebbe essere un'icona (ad esempio l'immagine di un pesce in decomposizione) o qualche altro indicatore.
Se l'utente ha prevalso sui meccanismi di cache in modo tale da ridurre anormalmente l'efficacia delle cache, lo user agent dovrebbe (SHOULD) indicare continuamente questo stato all'utente (ad esempio mostrando l'immagine di una banconota in fiamme), così che l'utente non consumi inavvertitamente risorse in eccesso né subisca latenze eccessive.
13.1.5 Exceptions to the Rules and Warnings (Eccezioni alle Regole e Avvisi)
In alcuni casi, chi gestisce una cache può (MAY) scegliere di configurarla per restituire risposte obsolete anche quando non sono richieste dai client. Questa decisione non va presa alla leggera, ma può essere necessaria per ragioni di disponibilità o prestazioni, specialmente quando la cache è mal collegata al server di origine. Ogni volta che una cache restituisce una risposta obsoleta, deve (MUST) contrassegnarla come tale (usando un'intestazione Warning), consentendo al software client di avvertire l'utente che potrebbe esserci un potenziale problema.
Ciò consente anche allo user agent di adottare misure per ottenere una risposta di prima mano o fresca. Per questo motivo, una cache non dovrebbe (SHOULD NOT) restituire una risposta obsoleta se il client ne richiede esplicitamente una di prima mano o fresca, a meno che sia impossibile conformarsi per ragioni tecniche o di politica.
13.1.6 Client-controlled Behavior (Comportamento Controllato dal Client)
Mentre il server di origine (e, in misura minore, le cache intermedie, per il loro contributo all'età di una risposta) è la fonte principale delle informazioni di scadenza, in alcuni casi il client può aver bisogno di controllare la decisione di una cache se restituire una risposta memorizzata senza rivalidarla. I client fanno questo usando diverse direttive dell'intestazione Cache-Control.
La richiesta di un client può (MAY) specificare l'età massima che è disposto ad accettare per una risposta non rivalidata; specificare il valore zero forza la o le cache a rivalidare tutte le risposte. Un client può (MAY) anche specificare il tempo minimo rimanente prima che una risposta scada. Entrambe queste opzioni aumentano i vincoli sul comportamento delle cache e quindi non possono allentare ulteriormente l'approssimazione della trasparenza semantica da parte della cache.
Un client può (MAY) anche specificare che accetterà risposte obsolete, fino a una certa quantità massima di obsolescenza. Questo allenta i vincoli sulle cache e quindi può violare i vincoli di trasparenza semantica specificati dal server di origine, ma può essere necessario per supportare il funzionamento disconnesso o un'elevata disponibilità in presenza di connettività scadente.
13.2 Expiration Model (Modello di Scadenza)
13.2.1 Server-Specified Expiration (Scadenza Specificata dal Server)
La cache HTTP funziona meglio quando le cache possono evitare del tutto di fare richieste al server di origine. Il meccanismo principale per evitare le richieste è che un server di origine fornisca un tempo di scadenza esplicito nel futuro, indicando che una risposta può (MAY) essere usata per soddisfare richieste successive. In altre parole, una cache può restituire una risposta fresca senza contattare prima il server.
La nostra aspettativa è che i server assegnino tempi di scadenza espliciti futuri alle risposte, nella convinzione che l'entità non cambierà probabilmente in modo semanticamente significativo prima che il tempo di scadenza sia raggiunto. Questo normalmente preserva la trasparenza semantica, purché i tempi di scadenza del server siano scelti con cura.
Il meccanismo di scadenza si applica solo alle risposte prelevate da una cache e non alle risposte di prima mano inoltrate immediatamente al client richiedente.
Se un server di origine desidera forzare una cache semanticamente trasparente a rivalidare ogni richiesta, può (MAY) assegnare un tempo di scadenza esplicito nel passato. Ciò significa che la risposta è sempre obsoleta, e quindi la cache dovrebbe (SHOULD) rivalidarla prima di usarla per richieste successive. Per un modo più restrittivo di forzare la rivalidazione, vedere la sezione 14.9.4.
Se un server di origine desidera forzare qualsiasi cache HTTP/1.1, comunque sia configurata, a rivalidare ogni richiesta, dovrebbe (SHOULD) usare la direttiva cache-control "must-revalidate" (vedere la sezione 14.9).
I server specificano tempi di scadenza espliciti usando l'intestazione Expires oppure la direttiva max-age dell'intestazione Cache-Control.
Un tempo di scadenza non può essere usato per forzare uno user agent ad aggiornare la propria visualizzazione o a ricaricare una risorsa; la sua semantica si applica solo ai meccanismi di cache, e tali meccanismi devono controllare lo stato di scadenza di una risorsa solo quando viene iniziata una nuova richiesta per quella risorsa. Per una spiegazione della differenza tra cache e meccanismi di cronologia, vedere la sezione 13.13.
13.2.2 Heuristic Expiration (Scadenza Euristica)
Poiché i server di origine non forniscono sempre tempi di scadenza espliciti, le cache HTTP tipicamente assegnano tempi di scadenza euristici, impiegando algoritmi che usano altri valori di intestazione (come il tempo Last-Modified) per stimare un tempo di scadenza plausibile. La specifica HTTP/1.1 non fornisce algoritmi specifici, ma impone vincoli nel caso peggiore sui loro risultati. Poiché i tempi di scadenza euristici possono compromettere la trasparenza semantica, vanno usati con cautela, e incoraggiamo i server di origine a fornire tempi di scadenza espliciti il più possibile.
13.2.3 Age Calculations (Calcoli dell'Età)
Per sapere se una voce memorizzata nella cache è fresca, una cache deve sapere se la sua età supera la sua durata di freschezza. Come calcolare quest'ultima è discusso nella sezione 13.2.4; questa sezione descrive come calcolare l'età di una risposta o di una voce di cache.
In questa discussione, usiamo il termine "now" per significare "il valore corrente dell'orologio sull'host che esegue il calcolo". Gli host che usano HTTP, ma specialmente gli host che eseguono server di origine e cache, dovrebbero (SHOULD) usare NTP [28] o un protocollo simile per sincronizzare i propri orologi con uno standard di tempo globalmente accurato.
HTTP/1.1 richiede ai server di origine di inviare un'intestazione Date, se possibile, con ogni risposta, indicando il momento in cui la risposta è stata generata (vedere la sezione 14.18). Usiamo il termine "date_value" per denotare il valore dell'intestazione Date, in una forma appropriata per operazioni aritmetiche.
HTTP/1.1 usa l'intestazione di risposta Age per trasmettere l'età stimata del messaggio di risposta quando è ottenuto da una cache. Il valore del campo Age è la stima della cache della quantità di tempo trascorsa da quando la risposta è stata generata o rivalidata dal server di origine.
In sostanza, il valore Age è la somma del tempo in cui la risposta è rimasta in ciascuna delle cache lungo il percorso dal server di origine, più la quantità di tempo in cui è stata in transito lungo i percorsi di rete.
Usiamo il termine "age_value" per denotare il valore dell'intestazione Age, in una forma appropriata per operazioni aritmetiche.
L'età di una risposta può essere calcolata in due modi del tutto indipendenti:
1. now meno date_value, se l'orologio locale è ragionevolmente ben sincronizzato con l'orologio del server di origine. Se il risultato è negativo, il risultato viene sostituito da zero.
2. age_value, se tutte le cache lungo il percorso della risposta implementano HTTP/1.1.
Dato che abbiamo due modi indipendenti per calcolare l'età di una risposta quando viene ricevuta, possiamo combinarli come
corrected_received_age = max(now - date_value, age_value)
e finché abbiamo orologi quasi sincronizzati oppure percorsi interamente HTTP/1.1, si ottiene un risultato affidabile (conservativo).
A causa dei ritardi imposti dalla rete, un intervallo significativo può trascorrere tra il momento in cui un server genera una risposta e il momento in cui essa viene ricevuta alla successiva cache o al client in uscita. Se non corretto, questo ritardo potrebbe produrre età inadeguatamente basse.
Poiché la richiesta che ha prodotto il valore Age restituito deve essere stata iniziata prima della generazione di quel valore Age, possiamo correggere i ritardi imposti dalla rete registrando il momento in cui la richiesta è stata iniziata. Poi, quando si riceve un valore Age, esso deve (MUST) essere interpretato rispetto al momento in cui la richiesta è stata iniziata, non al momento in cui la risposta è stata ricevuta. Questo algoritmo produce un comportamento conservativo indipendentemente da quanto ritardo si subisca. Quindi calcoliamo:
corrected_initial_age = corrected_received_age
+ (now - request_time)
dove "request_time" è il momento (secondo l'orologio locale) in cui è stata inviata la richiesta che ha suscitato questa risposta.
Riepilogo dell'algoritmo di calcolo dell'età, quando una cache riceve una risposta:
/*
* age_value
* is the value of Age: header received by the cache with
* this response.
* date_value
* is the value of the origin server's Date: header
* request_time
* is the (local) time when the cache made the request
* that resulted in this cached response
* response_time
* is the (local) time when the cache received the
* response
* now
* is the current (local) time
*/
apparent_age = max(0, response_time - date_value);
corrected_received_age = max(apparent_age, age_value);
response_delay = response_time - request_time;
corrected_initial_age = corrected_received_age + response_delay;
resident_time = now - response_time;
current_age = corrected_initial_age + resident_time;
Il current_age di una voce di cache è calcolato aggiungendo la quantità di tempo (in secondi) trascorsa da quando la voce di cache è stata rivalidata l'ultima volta dal server di origine al corrected_initial_age. Quando una risposta viene generata da una voce di cache, la cache deve (MUST) includere nella risposta un singolo campo di intestazione Age con un valore uguale al current_age della voce di cache.
La presenza di un campo di intestazione Age in una risposta implica che la risposta non è di prima mano. Tuttavia, non vale il contrario, poiché l'assenza di un campo di intestazione Age in una risposta non implica che la risposta sia di prima mano, a meno che tutte le cache lungo il percorso della richiesta siano conformi a HTTP/1.1 (vale a dire che le cache HTTP più vecchie non implementavano il campo di intestazione Age).
13.2.4 Expiration Calculations (Calcoli di Scadenza)
Per decidere se una risposta è fresca o obsoleta, dobbiamo confrontare la sua durata di freschezza con la sua età. L'età è calcolata come descritto nella sezione 13.2.3; questa sezione descrive come calcolare la durata di freschezza e come determinare se una risposta è scaduta. Nella discussione che segue, i valori possono essere rappresentati in qualsiasi forma appropriata per operazioni aritmetiche.
Usiamo il termine "expires_value" per denotare il valore dell'intestazione Expires. Usiamo il termine "max_age_value" per denotare un valore appropriato del numero di secondi portato dalla direttiva "max-age" dell'intestazione Cache-Control in una risposta (vedere la sezione 14.9.3).
La direttiva max-age ha priorità su Expires, quindi se max-age è presente in una risposta, il calcolo è semplicemente:
freshness_lifetime = max_age_value
Altrimenti, se Expires è presente nella risposta, il calcolo è:
freshness_lifetime = expires_value - date_value
Si noti che nessuno di questi calcoli è vulnerabile allo scostamento dell'orologio, poiché tutte le informazioni provengono dal server di origine.
Se nella risposta non compare né Expires né Cache-Control: max-age né Cache-Control: s-maxage (vedere la sezione 14.9.3), e la risposta non include altre restrizioni sulla memorizzazione nella cache, la cache può (MAY) calcolare una durata di freschezza usando un'euristica. La cache deve (MUST) allegare il Warning 113 a qualsiasi risposta la cui età superi le 24 ore, se tale avviso non è già stato aggiunto.
Inoltre, se la risposta ha un tempo Last-Modified, il valore di scadenza euristico non dovrebbe (SHOULD) superare una frazione dell'intervallo trascorso da quel momento. Un'impostazione tipica di questa frazione potrebbe essere il 10%.
Il calcolo per determinare se una risposta è scaduta è piuttosto semplice:
response_is_fresh = (freshness_lifetime > current_age)
13.2.5 Disambiguating Expiration Values (Disambiguazione dei Valori di Scadenza)
Poiché i valori di scadenza sono assegnati in modo ottimistico, è possibile che due cache contengano valori freschi diversi per la stessa risorsa.
Se un client che esegue un recupero riceve una risposta non di prima mano per una richiesta che era già fresca nella propria cache, e l'intestazione Date nella sua voce di cache esistente è più recente della Date nella nuova risposta, allora il client può (MAY) ignorare la risposta. In tal caso, può (MAY) ritentare la richiesta con una direttiva "Cache-Control: max-age=0" (vedere la sezione 14.9), per forzare un controllo con il server di origine.
Se una cache ha due risposte fresche per la stessa rappresentazione con validatori diversi, deve (MUST) usare quella con l'intestazione Date più recente. Questa situazione può sorgere perché la cache sta raccogliendo risposte da altre cache, o perché un client ha chiesto un ricaricamento o una rivalidazione di una voce di cache apparentemente fresca.
13.2.6 Disambiguating Multiple Responses (Disambiguazione di Risposte Multiple)
Poiché un client può ricevere risposte attraverso più percorsi, cosicché alcune risposte passano attraverso un insieme di cache e altre attraverso un insieme diverso di cache, un client può ricevere risposte in un ordine diverso da quello in cui il server di origine le ha inviate. Vorremmo che il client usasse la risposta generata più di recente, anche se risposte più vecchie sono ancora apparentemente fresche.
Né il tag di entità né il valore di scadenza possono imporre un ordinamento alle risposte, poiché è possibile che una risposta successiva porti intenzionalmente un tempo di scadenza anteriore. I valori Date sono ordinati con granularità di un secondo.
Quando un client tenta di rivalidare una voce di cache, e la risposta che riceve contiene un'intestazione Date che sembra anteriore a quella della voce esistente, allora il client dovrebbe (SHOULD) ripetere la richiesta incondizionatamente e includere
Cache-Control: max-age=0
per forzare qualsiasi cache intermedia a rivalidare le proprie copie direttamente con il server di origine, oppure
Cache-Control: no-cache
per forzare qualsiasi cache intermedia a ottenere una nuova copia dal server di origine.
Se i valori Date sono uguali, il client può (MAY) usare l'una o l'altra risposta (o può (MAY), se è estremamente prudente, richiedere una nuova risposta). I server non devono (MUST NOT) dipendere dal fatto che i client riescano a scegliere in modo deterministico tra risposte generate nello stesso secondo, se i loro tempi di scadenza si sovrappongono.
13.3 Validation Model (Modello di Validazione)
Quando una cache ha una voce obsoleta che vorrebbe usare come risposta alla richiesta di un client, deve prima controllare con il server di origine (o eventualmente con una cache intermedia che ha una risposta fresca) se la sua voce memorizzata è ancora utilizzabile. Chiamiamo questo "validare" la voce di cache. Poiché non vogliamo dover pagare il costo di ritrasmettere la risposta completa se la voce memorizzata è buona, e non vogliamo pagare il costo di un'andata e ritorno extra se la voce memorizzata non è valida, il protocollo HTTP/1.1 supporta l'uso di method condizionali.
Le funzionalità di protocollo chiave per supportare i method condizionali sono quelle relative ai "cache validator". Quando un server di origine genera una risposta completa, vi allega una sorta di validatore, che viene conservato insieme alla voce di cache. Quando un client (user agent o proxy cache) effettua una richiesta condizionale per una risorsa di cui ha una voce di cache, include il validatore associato nella richiesta.
Il server confronta poi quel validatore con il validatore corrente per l'entità e, se corrispondono (vedere la sezione 13.3.3), risponde con uno speciale codice di stato (di solito 304 (Not Modified)) e senza corpo dell'entità. In caso contrario, restituisce una risposta completa (compreso il corpo dell'entità). Così evitiamo di trasmettere la risposta completa se il validatore corrisponde, ed evitiamo un'andata e ritorno extra se non corrisponde.
In HTTP/1.1, una richiesta condizionale appare esattamente come una richiesta normale per la stessa risorsa, salvo che porta un'intestazione speciale (che include il validatore) che implicitamente trasforma il method (di solito GET) in condizionale.
Il protocollo include sia il senso positivo sia quello negativo delle condizioni di validazione della cache. Ossia, è possibile chiedere che un method sia eseguito se e solo se un validatore corrisponde, oppure se e solo se nessun validatore corrisponde.
Note: una risposta priva di validatore può comunque essere memorizzata nella cache e servita dalla cache fino alla sua scadenza, a meno che ciò sia esplicitamente vietato da una direttiva cache-control. Tuttavia, una cache non può eseguire un recupero condizionale se non ha un validatore per l'entità, il che significa che non sarà aggiornabile dopo la scadenza.
13.3.1 Last-Modified Dates (Date di Ultima Modifica)
Il valore del campo di intestazione di entità Last-Modified è spesso usato come validatore di cache. In termini semplici, una voce di cache è considerata valida se l'entità non è stata modificata dal valore Last-Modified in poi.
13.3.2 Entity Tag Cache Validators (Validatori di Cache con Tag di Entità)
Il valore del campo di intestazione di risposta ETag, un tag di entità, fornisce un validatore di cache "opaco". Questo può consentire una validazione più affidabile nelle situazioni in cui è scomodo memorizzare date di modifica, in cui la risoluzione di un secondo dei valori di data HTTP non è sufficiente, o in cui il server di origine desidera evitare certi paradossi che potrebbero derivare dall'uso di date di modifica.
I tag di entità sono descritti nella sezione 3.11. Le intestazioni usate con i tag di entità sono descritte nelle sezioni 14.19, 14.24, 14.26 e 14.44.
13.3.3 Weak and Strong Validators (Validatori Deboli e Forti)
Poiché sia i server di origine sia le cache confrontano due validatori per decidere se rappresentano la stessa entità o entità diverse, ci si aspetterebbe normalmente che, se l'entità (il corpo dell'entità o qualsiasi intestazione dell'entità) cambia in qualsiasi modo, anche il validatore associato cambi. Se questo è vero, chiamiamo tale validatore un "validatore forte".
Tuttavia, possono esserci casi in cui un server preferisce cambiare il validatore solo in caso di cambiamenti semanticamente significativi, e non quando cambiano aspetti insignificanti dell'entità. Un validatore che non cambia sempre quando la risorsa cambia è un "validatore debole".
I tag di entità sono normalmente "validatori forti", ma il protocollo prevede un meccanismo per contrassegnare un tag di entità come "debole". Si può pensare a un validatore forte come a uno che cambia ogni volta che cambiano i bit di un'entità, mentre un valore debole cambia ogni volta che cambia il significato di un'entità. In alternativa, si può pensare a un validatore forte come parte di un identificatore per una specifica entità, mentre un validatore debole è parte di un identificatore per un insieme di entità semanticamente equivalenti.
Note: un esempio di validatore forte è un intero che viene incrementato in memoria stabile ogni volta che un'entità viene modificata.
Il tempo di modifica di un'entità, se rappresentato con risoluzione di un secondo, potrebbe essere un validatore debole, poiché è possibile che la risorsa venga modificata due volte durante un solo secondo.
Il supporto per i validatori deboli è opzionale. Tuttavia, i validatori deboli consentono una memorizzazione nella cache più efficiente di oggetti equivalenti; ad esempio, un contatore di accessi su un sito è probabilmente sufficiente se viene aggiornato ogni pochi giorni o settimane, e qualsiasi valore durante quel periodo è probabilmente "abbastanza buono" per essere equivalente.
Un "uso" di un validatore avviene o quando un client genera una richiesta e include il validatore in un campo di intestazione di validazione, o quando un server confronta due validatori.
I validatori forti sono utilizzabili in qualsiasi contesto. I validatori deboli sono utilizzabili solo in contesti che non dipendono dall'esatta uguaglianza di un'entità. Ad esempio, entrambi i tipi sono utilizzabili per un GET condizionale di un'entità completa. Tuttavia, solo un validatore forte è utilizzabile per un recupero di sottointervallo, poiché altrimenti il client potrebbe ritrovarsi con un'entità internamente incoerente.
I client possono (MAY) emettere richieste GET semplici (non di sottointervallo) con validatori deboli o con validatori forti. I client non devono (MUST NOT) usare validatori deboli in altre forme di richiesta.
L'unica funzione che il protocollo HTTP/1.1 definisce sui validatori è il confronto. Esistono due funzioni di confronto dei validatori, a seconda che il contesto di confronto consenta o meno l'uso di validatori deboli:
- La funzione di confronto forte: per essere considerati uguali, entrambi i validatori devono (MUST) essere identici sotto ogni aspetto, e entrambi non devono (MUST NOT) essere deboli.
- La funzione di confronto debole: per essere considerati uguali, entrambi i validatori devono (MUST) essere identici sotto ogni aspetto, ma l'uno o l'altro o entrambi possono (MAY) essere contrassegnati come "deboli" senza che ciò influisca sul risultato.
Un tag di entità è forte a meno che non sia esplicitamente contrassegnato come debole. La sezione 3.11 fornisce la sintassi per i tag di entità.
Un tempo Last-Modified, quando è usato come validatore in una richiesta, è implicitamente debole, a meno che non sia possibile dedurre che è forte usando le seguenti regole:
- Il validatore è confrontato da un server di origine con l'attuale validatore corrente per l'entità, e
- Quel server di origine sa in modo affidabile che l'entità associata non è cambiata due volte durante il secondo coperto dal validatore presentato.
oppure
- Il validatore sta per essere usato da un client in un'intestazione If-Modified-Since o If-Unmodified-Since, perché il client ha una voce di cache per l'entità associata, e
- Quella voce di cache include un valore Date, che fornisce il momento in cui il server di origine ha inviato la risposta originale, e
- Il tempo Last-Modified presentato è anteriore al valore Date di almeno 60 secondi.
oppure
- Il validatore è confrontato da una cache intermedia con il validatore memorizzato nella sua voce di cache per l'entità, e
- Quella voce di cache include un valore Date, che fornisce il momento in cui il server di origine ha inviato la risposta originale, e
- Il tempo Last-Modified presentato è anteriore al valore Date di almeno 60 secondi.
Questo metodo si basa sul fatto che, se due risposte diverse sono state inviate dal server di origine durante lo stesso secondo, ma entrambe avevano lo stesso tempo Last-Modified, allora almeno una di quelle risposte avrebbe un valore Date uguale al suo tempo Last-Modified. Il limite arbitrario di 60 secondi protegge dalla possibilità che i valori Date e Last-Modified siano generati da orologi diversi, o in momenti alquanto diversi durante la preparazione della risposta. Un'implementazione può (MAY) usare un valore maggiore di 60 secondi, se si ritiene che 60 secondi siano troppo pochi.
Se un client desidera eseguire un recupero di sottointervallo su un valore per il quale ha solo un tempo Last-Modified e nessun validatore opaco, può (MAY) farlo solo se il tempo Last-Modified è forte nel senso qui descritto.
Una cache o un server di origine che riceve una richiesta condizionale diversa da una richiesta GET con corpo completo deve (MUST) usare la funzione di confronto forte per valutare la condizione.
Queste regole consentono alle cache e ai client HTTP/1.1 di eseguire in sicurezza recuperi di sottointervallo su valori ottenuti da server HTTP/1.0.
13.3.4 Rules for When to Use Entity Tags and Last-Modified Dates (Regole per Quando Usare Tag di Entità e Date di Ultima Modifica)
Adottiamo un insieme di regole e raccomandazioni per server di origine, client e cache su quando i vari tipi di validatore vadano usati e per quali scopi.
Server di origine HTTP/1.1:
- Dovrebbero (SHOULD) inviare un validatore di tag di entità, a meno che non sia fattibile generarne uno.
- Possono (MAY) inviare un tag di entità debole invece di un tag di entità forte, se considerazioni di prestazioni supportano l'uso di tag di entità deboli, o se non è fattibile inviare un tag di entità forte.
- Dovrebbero (SHOULD) inviare un valore Last-Modified se è fattibile inviarne uno, a meno che il rischio di una rottura della trasparenza semantica che potrebbe derivare dall'uso di questa data in un'intestazione If-Modified-Since non porti a problemi gravi.
In altre parole, il comportamento preferito per un server di origine HTTP/1.1 è inviare sia un tag di entità forte sia un valore Last-Modified.
Per essere legale, un tag di entità forte deve (MUST) cambiare ogni volta che il valore dell'entità associata cambia in qualsiasi modo. Un tag di entità debole dovrebbe (SHOULD) cambiare ogni volta che l'entità associata cambia in modo semanticamente significativo.
Note: per fornire una memorizzazione nella cache semanticamente trasparente, un server di origine deve evitare di riutilizzare uno specifico valore di tag di entità forte per due entità diverse, o di riutilizzare uno specifico valore di tag di entità debole per due entità semanticamente diverse. Le voci di cache possono persistere per periodi arbitrariamente lunghi, indipendentemente dai tempi di scadenza, quindi potrebbe essere inappropriato aspettarsi che una cache non tenti mai più di rivalidare una voce usando un validatore che ha ottenuto in qualche momento del passato.
Client HTTP/1.1:
- Se il server di origine ha fornito un tag di entità, devono (MUST) usare quel tag di entità in qualsiasi richiesta condizionale di cache (usando If-Match o If-None-Match).
- Se il server di origine ha fornito solo un valore Last-Modified, dovrebbero (SHOULD) usare quel valore nelle richieste condizionali di cache non di sottointervallo (usando If-Modified-Since).
- Se un server di origine HTTP/1.0 ha fornito solo un valore Last-Modified, possono (MAY) usare quel valore nelle richieste condizionali di cache di sottointervallo (usando If-Unmodified-Since). Lo user agent dovrebbe (SHOULD) fornire un modo per disabilitarlo, in caso di difficoltà.
- Se il server di origine ha fornito sia un tag di entità sia un valore Last-Modified, dovrebbero (SHOULD) usare entrambi i validatori nelle richieste condizionali di cache. Questo consente sia alle cache HTTP/1.0 sia a quelle HTTP/1.1 di rispondere in modo appropriato.
Un server di origine HTTP/1.1, nel ricevere una richiesta condizionale che include sia una data Last-Modified (ad esempio in un campo di intestazione If-Modified-Since o If-Unmodified-Since) sia uno o più tag di entità (ad esempio in un campo di intestazione If-Match, If-None-Match o If-Range) come validatori di cache, non deve (MUST NOT) restituire uno stato di risposta 304 (Not Modified) a meno che ciò non sia coerente con tutti i campi di intestazione condizionali della richiesta.
Un proxy di cache HTTP/1.1, nel ricevere una richiesta condizionale che include sia una data Last-Modified sia uno o più tag di entità come validatori di cache, non deve (MUST NOT) restituire al client una risposta memorizzata localmente a meno che quella risposta memorizzata non sia coerente con tutti i campi di intestazione condizionali della richiesta.
Note: il principio generale alla base di queste regole è che i server e i client HTTP/1.1 dovrebbero trasmettere quante più informazioni non ridondanti siano disponibili nelle loro risposte e richieste. I sistemi HTTP/1.1 che ricevono queste informazioni faranno le ipotesi più conservative sui validatori che ricevono.
I client e le cache HTTP/1.0 ignoreranno i tag di entità. In generale, i valori last-modified ricevuti o usati da questi sistemi supporteranno una memorizzazione nella cache trasparente ed efficiente, e quindi i server di origine HTTP/1.1 dovrebbero fornire valori Last-Modified. In quei rari casi in cui l'uso di un valore Last-Modified come validatore da parte di un sistema HTTP/1.0 potrebbe causare un problema grave, i server di origine HTTP/1.1 non dovrebbero fornirne uno.
13.3.5 Non-validating Conditionals (Condizionali Non Validanti)
Il principio alla base dei tag di entità è che solo l'autore del servizio conosce la semantica di una risorsa abbastanza bene da scegliere un meccanismo appropriato di validazione della cache, e che la specifica di qualsiasi funzione di confronto dei validatori più complessa dell'uguaglianza byte per byte aprirebbe un vaso di Pandora. Pertanto, i confronti di qualsiasi altra intestazione (tranne Last-Modified, per compatibilità con HTTP/1.0) non sono mai usati allo scopo di validare una voce di cache.
13.4 Response Cacheability (Memorizzabilità nella Cache della Risposta)
A meno che non sia specificamente vincolato da una direttiva cache-control (sezione 14.9), un sistema di cache può (MAY) sempre memorizzare una risposta riuscita (vedere la sezione 13.8) come voce di cache, può (MAY) restituirla senza validazione se è fresca, e può (MAY) restituirla dopo una validazione riuscita. Se a una risposta non è associato né un validatore di cache né un tempo di scadenza esplicito, non ci aspettiamo che venga memorizzata nella cache, ma certe cache possono (MAY) violare questa aspettativa (ad esempio quando è disponibile poca o nessuna connettività di rete). Un client può di solito rilevare che una tale risposta è stata prelevata da una cache confrontando l'intestazione Date con l'ora corrente.
Note: è noto che alcune cache HTTP/1.0 violano questa aspettativa senza fornire alcun Warning.
Tuttavia, in alcuni casi può essere inappropriato che una cache conservi un'entità o la restituisca in risposta a una richiesta successiva. Ciò può dipendere dal fatto che l'autore del servizio ritenga necessaria la trasparenza semantica assoluta, oppure da considerazioni di sicurezza o privacy. Sono quindi previste certe direttive cache-control, affinché il server possa indicare che certe entità di risorsa, o porzioni di esse, non devono essere memorizzate nella cache indipendentemente da altre considerazioni.
Si noti che la sezione 14.8 normalmente impedisce a una cache condivisa di salvare e restituire una risposta a una richiesta precedente se quella richiesta includeva un'intestazione Authorization.
Una risposta ricevuta con un codice di stato 200, 203, 206, 300, 301 o 410 può (MAY) essere memorizzata da una cache e usata in risposta a una richiesta successiva, fatti salvi i vincoli del meccanismo di scadenza, a meno che una direttiva cache-control non vieti la memorizzazione nella cache. Tuttavia, una cache che non supporta le intestazioni Range e Content-Range non deve (MUST NOT) memorizzare risposte 206 (Partial Content).
Una risposta ricevuta con qualsiasi altro codice di stato (ad esempio i codici di stato 302 e 307) non deve (MUST NOT) essere restituita in risposta a una richiesta successiva, a meno che non vi siano direttive cache-control o altre intestazioni che lo consentano esplicitamente. Ad esempio, tra queste vi sono: un'intestazione Expires (sezione 14.21); una direttiva cache-control "max-age", "s-maxage", "must-revalidate", "proxy-revalidate", "public" o "private" (sezione 14.9).
13.5 Constructing Responses From Caches (Costruzione di Risposte dalle Cache)
Lo scopo di una cache HTTP è memorizzare le informazioni ricevute in risposta alle richieste, per usarle nel rispondere a richieste future. In molti casi, una cache si limita a restituire al richiedente le parti appropriate di una risposta. Tuttavia, se la cache detiene una voce di cache basata su una risposta precedente, potrebbe dover combinare parti di una nuova risposta con ciò che è detenuto nella voce di cache.
13.5.1 End-to-end and Hop-by-hop Headers (Intestazioni End-to-End e Hop-by-Hop)
Al fine di definire il comportamento delle cache e dei proxy non di cache, dividiamo le intestazioni HTTP in due categorie:
- Intestazioni end-to-end, che sono trasmesse al destinatario finale di una richiesta o di una risposta. Le intestazioni end-to-end nelle risposte devono (MUST) essere memorizzate come parte di una voce di cache e devono (MUST) essere trasmesse in qualsiasi risposta formata da una voce di cache.
- Intestazioni hop-by-hop, che hanno significato solo per una singola connessione a livello di trasporto, e non sono memorizzate dalle cache né inoltrate dai proxy.
Le seguenti intestazioni HTTP/1.1 sono intestazioni hop-by-hop:
- Connection
- Keep-Alive
- Proxy-Authenticate
- Proxy-Authorization
- TE
- Trailers
- Transfer-Encoding
- Upgrade
Tutte le altre intestazioni definite da HTTP/1.1 sono intestazioni end-to-end.
Altre intestazioni hop-by-hop devono (MUST) essere elencate in un'intestazione Connection (sezione 14.10) per essere introdotte in HTTP/1.1 (o successive).
13.5.2 Non-modifiable Headers (Intestazioni Non Modificabili)
Alcune funzionalità del protocollo HTTP/1.1, come la Digest Authentication, dipendono dal valore di certe intestazioni end-to-end. Un proxy trasparente non dovrebbe (SHOULD NOT) modificare un'intestazione end-to-end, a meno che la definizione di tale intestazione lo richieda o lo consenta specificamente.
Un proxy trasparente non deve (MUST NOT) modificare nessuno dei seguenti campi in una richiesta o risposta, e non deve (MUST NOT) aggiungere nessuno di questi campi se non già presenti:
- Content-Location
- Content-MD5
- ETag
- Last-Modified
Un proxy trasparente non deve (MUST NOT) modificare nessuno dei seguenti campi in una risposta:
- Expires
ma può (MAY) aggiungere uno qualsiasi di questi campi se non già presenti. Se viene aggiunta un'intestazione Expires, le deve (MUST) essere dato un field-value identico a quello dell'intestazione Date in quella risposta.
Un proxy non deve (MUST NOT) modificare o aggiungere nessuno dei seguenti campi in un messaggio che contiene la direttiva cache-control no-transform, né in alcuna richiesta:
- Content-Encoding
- Content-Range
- Content-Type
Un proxy non trasparente può (MAY) modificare o aggiungere questi campi a un messaggio che non include no-transform, ma se lo fa deve (MUST) aggiungere un Warning 214 (Transformation applied) se non ne compare già uno nel messaggio (vedere la sezione 14.46).
Warning: unnecessary modification of end-to-end headers might
cause authentication failures if stronger authentication
mechanisms are introduced in later versions of HTTP. Such
authentication mechanisms MAY rely on the values of header fields
not listed here.
Il campo Content-Length di una richiesta o risposta viene aggiunto o eliminato secondo le regole della sezione 4.4. Un proxy trasparente deve (MUST) preservare l'entity-length (sezione 7.2.2) del corpo dell'entità, sebbene possa (MAY) cambiare la transfer-length (sezione 4.4).
13.5.3 Combining Headers (Combinazione di Intestazioni)
Quando una cache effettua una richiesta di validazione a un server, e il server fornisce una risposta 304 (Not Modified) o una risposta 206 (Partial Content), la cache costruisce poi una risposta da inviare al client richiedente.
Se il codice di stato è 304 (Not Modified), la cache usa il corpo dell'entità memorizzato nella voce di cache come corpo dell'entità di questa risposta in uscita. Se il codice di stato è 206 (Partial Content) e le intestazioni ETag o Last-Modified corrispondono esattamente, la cache può (MAY) combinare i contenuti memorizzati nella voce di cache con i nuovi contenuti ricevuti nella risposta e usare il risultato come corpo dell'entità di questa risposta in uscita (vedere la sezione 13.5.4).
Le intestazioni end-to-end memorizzate nella voce di cache sono usate per la risposta costruita, salvo che
- qualsiasi intestazione Warning memorizzata con warn-code 1xx (vedere la sezione 14.46) deve (MUST) essere eliminata dalla voce di cache e dalla risposta inoltrata.
- qualsiasi intestazione Warning memorizzata con warn-code 2xx deve (MUST) essere mantenuta nella voce di cache e nella risposta inoltrata.
- qualsiasi intestazione end-to-end fornita nella risposta 304 o 206 deve (MUST) sostituire le intestazioni corrispondenti della voce di cache.
A meno che la cache decida di rimuovere la voce di cache, deve (MUST) anche sostituire le intestazioni end-to-end memorizzate con la voce di cache con le intestazioni corrispondenti ricevute nella risposta in arrivo, eccetto le intestazioni Warning come descritto immediatamente sopra. Se un header field-name nella risposta in arrivo corrisponde a più di un'intestazione nella voce di cache, tutte quelle vecchie intestazioni devono (MUST) essere sostituite.
In altre parole, l'insieme delle intestazioni end-to-end ricevute nella risposta in arrivo prevale su tutte le intestazioni end-to-end corrispondenti memorizzate con la voce di cache (eccetto le intestazioni Warning memorizzate con warn-code 1xx, che vengono eliminate anche se non sostituite).
Note: questa regola consente a un server di origine di usare una risposta 304 (Not Modified) o 206 (Partial Content) per aggiornare qualsiasi intestazione associata a una risposta precedente per la stessa entità o suoi sottointervalli, sebbene ciò non sia sempre significativo o corretto. Questa regola non consente a un server di origine di usare una risposta 304 (Not Modified) o 206 (Partial Content) per eliminare del tutto un'intestazione che aveva fornito con una risposta precedente.
13.5.4 Combining Byte Ranges (Combinazione di Intervalli di Byte)
Una risposta potrebbe trasferire solo un sottointervallo dei byte di un corpo dell'entità, sia perché la richiesta includeva una o più specifiche Range, sia perché una connessione si è interrotta prematuramente. Dopo diversi trasferimenti di questo tipo, una cache potrebbe aver ricevuto diversi intervalli dello stesso corpo dell'entità.
Se una cache ha un insieme memorizzato non vuoto di sottointervalli per un'entità, e una risposta in arrivo trasferisce un altro sottointervallo, la cache può (MAY) combinare il nuovo sottointervallo con l'insieme esistente se sono soddisfatte entrambe le seguenti condizioni:
- Sia la risposta in arrivo sia la voce di cache hanno un validatore di cache.
- I due validatori di cache corrispondono usando la funzione di confronto forte (vedere la sezione 13.3.3).
Se uno dei due requisiti non è soddisfatto, la cache deve (MUST) usare solo la risposta parziale più recente (in base ai valori Date trasmessi con ogni risposta, usando la risposta in arrivo se questi valori sono uguali o mancanti) e deve (MUST) scartare le altre informazioni parziali.
13.6 Caching Negotiated Responses (Caching di Risposte Negoziate)
L'uso della negoziazione del contenuto guidata dal server (sezione 12.1), indicata dalla presenza di un campo di intestazione Vary in una risposta, altera le condizioni e la procedura con cui una cache può usare la risposta per richieste successive. Per l'uso del campo di intestazione Vary da parte dei server, vedere la sezione 14.44.
Un server dovrebbe (SHOULD) usare il campo di intestazione Vary per informare una cache di quali campi di intestazione di richiesta sono stati usati per scegliere tra più rappresentazioni di una risposta memorizzabile nella cache soggetta a negoziazione guidata dal server. L'insieme dei campi di intestazione nominati dal valore del campo Vary è noto come request-header "selecting".
Quando la cache riceve una richiesta successiva il cui Request-URI specifica una o più voci di cache che includono un campo di intestazione Vary, la cache non deve (MUST NOT) usare tale voce di cache per costruire una risposta alla nuova richiesta, a meno che tutti i request-header selecting presenti nella nuova richiesta non corrispondano ai corrispondenti request-header memorizzati nella richiesta originale.
I request-header selecting di due richieste si definiscono corrispondenti se e solo se i request-header selecting della prima richiesta possono essere trasformati nei request-header selecting della seconda richiesta aggiungendo o rimuovendo spazio bianco lineare (LWS) nei punti in cui ciò è consentito dal corrispondente BNF, e/o combinando più campi message-header con lo stesso field name secondo le regole sui message header della sezione 4.2.
Un field-value dell'intestazione Vary pari a "*" non corrisponde mai, e le richieste successive su quella risorsa possono essere interpretate correttamente solo dal server di origine.
Se i campi di intestazione di richiesta selecting per la voce memorizzata non corrispondono ai campi di intestazione di richiesta selecting della nuova richiesta, allora la cache non deve (MUST NOT) usare una voce memorizzata per soddisfare la richiesta, a meno che non inoltri prima la nuova richiesta al server di origine come richiesta condizionale e il server risponda con 304 (Not Modified), includendo un tag di entità o un Content-Location che indichi l'entità da usare.
Se a una rappresentazione memorizzata nella cache è stato assegnato un tag di entità, la richiesta inoltrata dovrebbe (SHOULD) essere condizionale e includere i tag di entità in un campo di intestazione If-None-Match da tutte le sue voci di cache per la risorsa. Questo comunica al server l'insieme delle entità attualmente detenute dalla cache, così che, se una qualsiasi di queste entità corrisponde all'entità richiesta, il server possa usare il campo di intestazione ETag nella sua risposta 304 (Not Modified) per dire alla cache quale voce è appropriata. Se l'entity-tag della nuova risposta corrisponde a quello di una voce esistente, la nuova risposta dovrebbe (SHOULD) essere usata per aggiornare i campi di intestazione della voce esistente, e il risultato deve (MUST) essere restituito al client.
Se una qualsiasi delle voci di cache esistenti contiene solo contenuto parziale per l'entità associata, il suo entity-tag non dovrebbe (SHOULD NOT) essere incluso nel campo di intestazione If-None-Match, a meno che la richiesta non riguardi un intervallo che sarebbe completamente soddisfatto da quella voce.
Se una cache riceve una risposta riuscita il cui campo Content-Location corrisponde a quello di una voce di cache esistente per lo stesso Request-URI, il cui entity-tag differisce da quello della voce esistente, e la cui Date è più recente di quella della voce esistente, la voce esistente non dovrebbe (SHOULD NOT) essere restituita in risposta a richieste future e dovrebbe (SHOULD) essere eliminata dalla cache.
13.7 Shared and Non-Shared Caches (Cache Condivise e Non Condivise)
Per ragioni di sicurezza e privacy, è necessario distinguere tra cache "condivise" e "non condivise". Una cache non condivisa è una cache accessibile a un solo utente. In questo caso l'accessibilità dovrebbe (SHOULD) essere garantita da meccanismi di sicurezza appropriati. Tutte le altre cache sono considerate "condivise". Altre sezioni di questa specifica pongono certi vincoli sul funzionamento delle cache condivise, allo scopo di prevenire la perdita di privacy o il fallimento dei controlli di accesso.
13.8 Errors or Incomplete Response Cache Behavior (Comportamento della Cache per Errori o Risposte Incomplete)
Una cache che riceve una risposta incompleta (ad esempio con meno byte di dati di quanti specificati in un'intestazione Content-Length) può (MAY) memorizzare la risposta. Tuttavia, la cache deve (MUST) trattarla come risposta parziale. Le risposte parziali possono (MAY) essere combinate come descritto nella sezione 13.5.4; il risultato potrebbe essere una risposta completa o potrebbe essere ancora parziale. Una cache non deve (MUST NOT) restituire una risposta parziale a un client senza contrassegnarla esplicitamente come tale, usando il codice di stato 206 (Partial Content). Una cache non deve (MUST NOT) restituire una risposta parziale usando un codice di stato 200 (OK).
Se una cache riceve una risposta 5xx mentre tenta di rivalidare una voce, può (MAY) inoltrare questa risposta al client richiedente, oppure comportarsi come se il server non avesse risposto. In quest'ultimo caso, può (MAY) restituire una risposta ricevuta in precedenza, a meno che la voce memorizzata non includa la direttiva cache-control "must-revalidate" (vedere la sezione 14.9).
13.9 Side Effects of GET and HEAD (Effetti Collaterali di GET e HEAD)
A meno che il server di origine non vieti esplicitamente la memorizzazione nella cache delle loro risposte, l'applicazione dei method GET e HEAD a qualsiasi risorsa non dovrebbe (SHOULD NOT) avere effetti collaterali che porterebbero a un comportamento erroneo se queste risposte fossero prelevate da una cache. Possono (MAY) comunque avere effetti collaterali, ma una cache non è tenuta a considerare tali effetti collaterali nelle proprie decisioni di memorizzazione nella cache. Ci si aspetta sempre che le cache rispettino le restrizioni esplicite di un server di origine sulla memorizzazione nella cache.
Notiamo un'eccezione a questa regola: poiché alcune applicazioni hanno tradizionalmente usato GET e HEAD con URL di query (quelli contenenti un "?" nella parte rel_path) per eseguire operazioni con effetti collaterali significativi, le cache non devono (MUST NOT) trattare come fresche le risposte a tali URI, a meno che il server non fornisca un tempo di scadenza esplicito. Questo significa specificamente che le risposte provenienti da server HTTP/1.0 per tali URI non dovrebbero (SHOULD NOT) essere prelevate da una cache. Per informazioni correlate, vedere la sezione 9.1.1.
13.10 Invalidation After Updates or Deletions (Invalidazione Dopo Aggiornamenti o Cancellazioni)
L'effetto di certi method eseguiti su una risorsa presso il server di origine può rendere una o più voci di cache esistenti non trasparentemente non valide. Ossia, sebbene possano continuare a essere "fresche", non riflettono accuratamente ciò che il server di origine restituirebbe per una nuova richiesta su quella risorsa.
Il protocollo HTTP non ha modo di garantire che tutte queste voci di cache siano contrassegnate come non valide. Ad esempio, la richiesta che ha causato il cambiamento presso il server di origine potrebbe non essere passata attraverso il proxy dove è memorizzata una voce di cache. Tuttavia, diverse regole aiutano a ridurre la probabilità di comportamenti erronei.
In questa sezione, l'espressione "invalidare un'entità" significa che la cache rimuoverà tutte le istanze di quell'entità dalla propria memoria, oppure le contrassegnerà come "non valide" e bisognose di una rivalidazione obbligatoria prima di poter essere restituite in risposta a una richiesta successiva.
Alcuni method HTTP devono (MUST) far sì che una cache invalidi un'entità. Si tratta dell'entità a cui fa riferimento il Request-URI, oppure delle intestazioni Location o Content-Location (se presenti). Questi method sono:
- PUT
- DELETE
- POST
Per prevenire attacchi di negazione del servizio, un'invalidazione basata sull'URI in un'intestazione Location o Content-Location deve (MUST) essere eseguita solo se la parte host è la stessa del Request-URI.
Una cache che lascia passare richieste per method che non comprende dovrebbe (SHOULD) invalidare qualsiasi entità a cui fa riferimento il Request-URI.
13.11 Write-Through Mandatory (Scrittura Diretta Obbligatoria)
Tutti i method che si può prevedere causino modifiche alle risorse del server di origine devono (MUST) essere scritti direttamente (write-through) sul server di origine. Attualmente questo include tutti i method tranne GET e HEAD. Una cache non deve (MUST NOT) rispondere a una tale richiesta di un client prima di aver trasmesso la richiesta al server di ingresso e di aver ricevuto una risposta corrispondente dal server di ingresso. Ciò non impedisce a un proxy cache di inviare una risposta 100 (Continue) prima che il server di ingresso abbia inviato la sua risposta finale.
L'alternativa (nota come cache "write-back" o "copy-back") non è consentita in HTTP/1.1, a causa della difficoltà di fornire aggiornamenti coerenti e dei problemi che sorgono da guasti del server, della cache o della rete prima della write-back.
13.12 Cache Replacement (Sostituzione della Cache)
Se una nuova risposta memorizzabile nella cache (vedere le sezioni 14.9.2, 13.2.5, 13.2.6 e 13.8) viene ricevuta da una risorsa mentre sono memorizzate risposte esistenti per la stessa risorsa, la cache dovrebbe (SHOULD) usare la nuova risposta per rispondere alla richiesta corrente. Può (MAY) inserirla nella memoria della cache e può (MAY), se soddisfa tutti gli altri requisiti, usarla per rispondere a qualsiasi richiesta futura che in precedenza avrebbe causato la restituzione della vecchia risposta. Se inserisce la nuova risposta nella memoria della cache, si applicano le regole della sezione 13.5.3.
Note: una nuova risposta che ha un valore dell'intestazione Date anteriore a quello delle risposte memorizzate esistenti non è memorizzabile nella cache.
13.13 History Lists (Elenchi Storici)
Gli user agent hanno spesso meccanismi di cronologia, come i pulsanti "Indietro" e gli elenchi storici, che possono essere usati per rimostrare un'entità recuperata in precedenza in una sessione.
I meccanismi di cronologia e le cache sono diversi. In particolare, i meccanismi di cronologia non dovrebbero (SHOULD NOT) cercare di mostrare una visione semanticamente trasparente dello stato corrente di una risorsa. Piuttosto, un meccanismo di cronologia serve a mostrare esattamente ciò che l'utente ha visto nel momento in cui la risorsa è stata recuperata.
Per impostazione predefinita, un tempo di scadenza non si applica ai meccanismi di cronologia. Se l'entità è ancora in memoria, un meccanismo di cronologia dovrebbe (SHOULD) visualizzarla anche se l'entità è scaduta, a meno che l'utente non abbia specificamente configurato l'agent per aggiornare i documenti di cronologia scaduti.
Questo non va interpretato come un divieto per il meccanismo di cronologia di comunicare all'utente che una vista potrebbe essere obsoleta.
Note: se i meccanismi di elenco storico impediscono inutilmente agli utenti di vedere risorse obsolete, questo tenderà a costringere gli autori dei servizi a evitare di usare i controlli di scadenza e di cache di HTTP quando altrimenti vorrebbero farlo. Gli autori dei servizi possono considerare importante che agli utenti non vengano presentati messaggi di errore o messaggi di avviso quando usano controlli di navigazione (come BACK) per vedere risorse recuperate in precedenza. Anche se a volte tali risorse non dovrebbero essere memorizzate nella cache, o dovrebbero scadere rapidamente, considerazioni sull'interfaccia utente possono costringere gli autori dei servizi a ricorrere ad altri mezzi per prevenire la memorizzazione nella cache (ad esempio URL "once-only") per non subire gli effetti di meccanismi di cronologia che funzionano in modo improprio.