asp - asp.net - aspcode.it

COMMUNITY - Login
 Username:
 
 Password:
 
Voglio registrarmi!
Password dimenticata?
 Utenti on-line: 0
 Ospiti on-line: 8735
ASPCode.it - Store

  > > Articoli

Gestione corretta della cache dei browser

Data di pubblicazione: 13/10/2003        Voto della community: 4,68 (Votanti: 46)


La gestione della cache nei browser, per stessa ammissione della www.w3.org, è da sempre alquanto approssimata. Per siti aggiornati frequentemente si preferisce escluderla a priori, per quelli invece con cambiamenti variabili nel tempo tuttora non esiste una tecnica per determinare se il contenuto del sito in cache coincida o meno con la versione online. Ora, con un semplice algoritmo lato server GPL, ipotizzo una soluzione per la gestione efficiente della cache.

Tutti i browser utilizzano una directory dedicata per memorizzare, per un periodo più o meno lungo scelto dall'utente, i contenuti delle pagine visitate durante la navigazione. Questo processo di caching viene attuato con lo scopo di accelerare la visualizzazione di una pagina internet nelle visite successive alla prima apertura della stessa, prelevandone il contenuto dalla cache memorizzata sull'hard disk, piuttosto che di ricaricarne nuovamente una copia (spesso uguale) dal server. Da sottolineare comunque che non è indicato applicare tale tecnica a siti web i cui contenuti vengano aggiornati di frequente. In tal caso, anzi, è consigliato disabilitare previamente la memorizzazione nella cache del browser onde evitare lo spiacevole inconveniente di mostrare il contenuto presente in cache, divenuto ormai obsoleto e non corrispondente a quello online.

Costruire e gestire siti che usano la cache è semplice. Ogni browser può memorizzare in cache le pagine che sta visitando: l'utente (il navigatore, o web-surfer che dir si voglia) può impostare un numero arbitario di giorni, dopo i quali i contenuti nella cache vengono cancellati. Queste pagine non possono usare i tags che incontreremo nel seguito.

Esistono numerose tecniche lato client, non efficaci al 100% (per stessa ammissione della www.w3.org, l'organismo che sovrintende la standardizzazione dei linguaggi della rete, come HTML e XML), per indicare ad un browser la necessità di non memorizzare in cache il contenuto di una determinata pagina internet. Vediamone ora alcuni. Tutti si basano sui tag META html e http header.

I META tags

I META tag sono etichette inserite in pagine HTML, ASP, PHP o, più genericamente, XML, utilizzate per indicare elementi di contenuto specifico. In particolare i tag (<meta>) aggiungono informazione alla pagina nella quale sono contenuti, ovvero forniscono, generalmente, informazione aggiuntiva circa una pagina web. I motori di ricerca, per esempio, possono usare l'informazione contenuta in determinati <meta> tags per l'indicizzazione della pagina nel loro database. Altri <meta> tag sono utilizzati dai web server. I tag META devono essere sempre posti tra i tag <head> prima del tag <body>.

Ci sono quindi tag per la descrizione del contenuto di una pagina:

<META name="description" CONTENT="Correct IE cache use methods">

altri per l'indicizzazione della pagina in cui sono contenuti nei motori di ricerca:

<META name="keywords" CONTENT="broswer cache caching management pragma no-cache">

altri per indicare l'autore:

<META name="author" CONTENT="John Doe">

o i copyright:

<META name="copyright" CONTENT="© 2000-2003 Marco Brera">

Ma i più interessanti sono i seguenti, utilizzati nell'HTTP header:

META Cache-Control
Il seguente meta tag impedisce, con efficacia non assoluta, la memorizzazione in cache della pagina:

<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">

META Expires
Esiste inoltre la possibilità di specificare il tempo di vita di una pagina in cache. Nel meta tag seguente è indicato l'istante fino al quale il browser userà la versione della pagina in cache. Ciò significa che il browser continuerà ad usare la versione in cache fino al raggiungimento della data indicata. Se si specifica una data del passato, o '0', si ha il download immediato della pagina da server, cosicchè il contenuto della cache viene aggiornato. Il formato delle date deve essere in Greenwich Mean Time (GMT), e non PST o EST, secondo quanto mostrato nell'esempio sotto.

<META HTTP-EQUIV="Expires" CONTENT="Tue, 20 Aug 2014 14:25:27 GMT">

La data rappresenta l'istante dopo cui il browser effettuerà il download dei contenuti della pagina web dal server anzichè dalla cache; in ogni caso, se la data è anteriore a quella della pubblicazione della pagina, il download partirà istantaneamente. In particolare, utilizzare questo META tag per aggiornare la cache immediatamente:

<META HTTP-EQUIV="Expires" CONTENT="0">

META Pragma
Esiste un'altro modo per controllare il caching del browser. Per utilizzare questo tag, il valore deve essere impostato su "no-cache". Quando è inserito in un documento, esso previene la memorizzazioe locale in cache da parte del browser:

<META HTTP-EQUIV="Pragma" CONTENT="no-cache">

<META> tag quali Cache-Control, Expires e Pragma possono essere usati insieme per mantenere corrente il contenuto di una pagina:

<!-- BEGIN INSERT-->
<META HTTP-EQUIV="Expires" CONTENT="Mon, 10 Sep 2001 00:00:00 GMT">
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<!-- END INSERT-->

Attenzione: esistono prove documentate secondo cui Internet Explorer ignora questi META tag, e pertanto memorizza ugualmente i file in cache.

Esistono dei casi documentati che testimoniano l'inefficacia dei META tag sopra indicati, cosicché i file vengono ugualmente memorizzati in cache. E' necessario quindi utilizzare metodi più efficaci per impedire la registrazione locale di una pagina in cache, forzando il browser a downloadare dal server ogni elemento contenuto nella pagina. Questa è l'unica soluzione corretta da adottare quando una pagina è soggetta ad aggiornamenti frequenti.
Macromedia, nella pagina "How to prevent cacing of swf files", suggerisce un metodo, con efficacia prossima al 100%, per il download forzato.
Il concetto base consiste nel variare i nomi dei file degli elementi contenuti nella pagina, aggiungendo di volta in volta, al nome base del file, un valore numerico diverso per ogni visita della pagina.
Solitamente, il cambiamento del nome è realizzato aggiungendo, alla sua fine, un numero casuale o la data e ora corrente. Cambiando il nome di ciascun file, il browser sarà forzato al download dal server, in quanto "penserà" che la pagina contenga file differenti, elementi diversi che saranno scaricati, registrando più versioni in cache, tutte con nomi differenti.
Qui di seguito sono presentate le soluzioni in tre diversi linguaggi:

JavaScript

<!-- BEGIN INSERT-->
<script language="JavaScript">
<!-- END INSERT-->
...
<!-- FOR EACH TEXTUAL AND GRAPHICAL ELEMENT-->
document.write('< img src="image.jpg?' + new Date().getTime() + '">')
//-->
</script>

PHP

<!-- BEGIN INSERT-->
<?php
header ("cache-control: no-cache, must-revalidate");
header ("pragma: no-cache");
header ("expires: Mon, 14 Aug 2010 00:00:00 GMT");
header ("last-modified: " . gmdate("D, d M Y H:i:s") . " GMT");
srand((double)microtime()*1000000);
$random_number = rand();
?>
<!-- END INSERT-->
...
<!-- FOR EACH TEXTUAL AND GRAPHICAL ELEMENT-->
<img src="image.jpg?<?echo $random_number;?>">

ASP

<!-- BEGIN INSERT-->
<%
Response.CacheControl = "no-cache"
Response.AddHeader "pragma", "no-cache"
Response.Expires = 0
RANDOMIZE
random_number = int(1000000*rnd)
%>
<!-- END INSERT-->
...
<!-- FOR EACH TEXTUAL AND GRAPHICAL ELEMENT-->
<img src="image.jpg?<%=random_number%>">

Aggiornamento della cache solo quando il contenuto della pagina viene modificato

Nelle sezioni precedenti abbiamo visto quanto la gestione della cache nei browser sia approssimativa, e come i risultati non siano sicuri. Abbiamo tutti bisogno di un metodo per la gestione intelligente della cache: vorremmo avere una tecnica che garantisse l'aggiornamento della cache del browser quando il suo contenuto è divenuto obsoleto rispetto alla versione online.
Come realizzare tutto ciò? Con uno script lato server.
L'ho realizzato in ASP, ma gli stessi risultati possono essere ottenuti, per esempio, con PHP.

Analizziamo l'algoritmo:
ho pensato di creare un cookie, contenente:
* la data dell'ultima versione del sito presente in cache;
* codice numerico: un numero casuale compreso tra 0 e 9999999

Possono presentarsi diversi casi:

A) Il cookie non esiste: è la prima volta che il browser del visitatore visita il sito, dunque creo il cookie.
La data che è scritta nel cookie è la data (con formato data+ora) dell'ultima modifica al sito, mentre il codice è un numero, tra 0 e 9999999, generato casualmente.

B) Se il cookie esiste, si possono verificare due sottocasi:
B1) La data memorizzata nel cookie coincide con la data dell'ultima modifica del sito. In questo caso lo script ASP legge il codice random registrato nel cookie.
B2) La data registrata è differente: ciò indica che il sito online è più recente rispetto a quello presente nella cache. In questo caso lo script ASP allora registra nel cookie la data dell'ultima modifica al sito e un nuovo codice numerico.

Qualcuno ora si domanderà la funzione dell'algoritmo proposto...forse altri avranno capito che il suo ruolo è un po' differente da quello per garantire l'applicazione dei metodi visti prima, in Javascript, PHP o ASP, per evitare il caching del sito. Ora si utilizza la cache: se il sito non è stato modificato dall'ultima visita viene letto dalla cache, viceversa, se è stato aggiornato, se ne memorizza una nuova copia in cache pronta per le successive visite. A questo punto è necessario dire che il nome di ogni file elemento grafico, testuale o di altra natura incluso nelle pagine del sito dovrà essere formattato con la sintassi vista precedentemente: elemento?codice_del_cookie.

Lo script ASP realizzato

Quello che segue è SOLO un esempio, adattabile facilmente alle esigenze più varie. Esso è costituito da tre parti:
- la prima verifica che i cookies del browser siano abilitati;
- la seconda gestisce la lettura/scrittura del cookie;
- la terza mostra il codice per la lettura dal cookie della data e del codice numerico.

1 - Verifica dell'abilitazione dei cookie

<%
'--------------
'Author: Marco Brera MarcoB@systems.it
'verify_cookie_enabled.asp:
'You may run or insert this code everywhere:
'it verifies if browser cookies are turned on
'--------------
If Request.ServerVariables("HTTP_COOKIE") = "" Then
  Response.Write "Your browser does not have cookies enabled!<br>"
  Response.Write "Please turn them on and retry<br>"
End If
%>

2 - E' necessario leggere il cookie (se esiste) e/o scriverci dati nuovi

<%
'--------------
'Author: Marco Brera MarcoB@systems.it
'read_date_code.asp:
' cookie reading/writing
'--------------
' insert name of cookie as you want
dim cookie_name
cookie_name = "cookie_name"
' read last modified date of html file
dim last_modified_date
Set FSO = CreateObject("Scripting.FileSystemObject")
' modify path and main.htm with the correct contents
Set File = FSO.GetFile(Server.MapPath(".") & "\main.htm")
last_modified_date = File.DateLastModified
dim rnd_n
If Request.Cookies(cookie_name).HasKeys Then
  ' date & code reading
  dim date
  dim code
  date = Request.Cookies(cookie_name)("date")
  code = Request.Cookies(cookie_name)("code")
  If StrComp(date,last_modified_date, 0)= 0 Then
    loading_code = code
  Else
    ' Cookie updating
    Response.Cookies(cookie_name)("date") = last_modified_date
    RANDOMIZE
    rnd_n = int(9999999*Rnd(1))
    Response.Cookies(cookie_name)("code") = rnd_n
    loading_code = rnd_n
    ' Expiration date updating
    Response.Cookies (cookie_name).Expires = Now() + 365
  End If
Else ' Cookie doesn't exist: I write it
  Response.Cookies(cookie_name)("date") = last_modified_date
  RANDOMIZE
  rnd_n = int(9999999*Rnd(1))
  Response.Cookies(cookie_name)("code") = rnd_n
  loading_code = rnd_n
  Response.Cookies (cookie_name).Expires = Now() + 365
End If
%>

3 - Una volta che read_date_code.asp è stato eseguito, si possono leggere i dati del cookie e sfruttare i dati stessi in ogni pagina ASP del sito, utilizzando solo le due espressioni seguenti:

Request.Cookies(cookie_name)("date")
Request.Cookies(cookie_name)("code")

Esempio:

<%
' insert name of cookie as you want
cookie_name="cookie_name"
date = Request.Cookies(cookie_name)("date")
code = Request.Cookies(cookie_name)("code")
%>

Questo algoritmo è stato reliazzato con una Licenza Pubblica GNU GPL. Potete quindi distribuire liberamente e gratuitamente questo codice con qualsiasi mezzo o supporto, per scopi non commerciali, mantenendo il riferimento dell'autore Marco Brera. Prego contattarmi per ogni suggerimento, sviluppo futuro, upgrade e informazione.


Si ringrazia Marco Brera per la gentile concessione dell'articolo.




Utenti connessi: 8735