Domanda

Sto scrivendo un metodo di gestione delle risorse in cui controllo l'accesso a vari file e mi piacerebbe poter utilizzare la cache del browser.La mia domanda è duplice:

  1. Quali sono le intestazioni HTTP definitive che devo controllare per sapere con certezza se devo inviare una risposta 304 e cosa cerco quando le controllo?

  2. Inoltre, ci sono intestazioni che devo inviare quando invio inizialmente il file (come "Ultima modifica") come risposta 200?

Alcuni pseudo-codici sarebbero probabilmente la risposta più utile.


E l'intestazione del controllo della cache?I vari valori possibili possono influenzare ciò che invii al client (vale a dire l'età massima) o dovrebbero essere rispettati solo se modificati dal momento che?

È stato utile?

Soluzione

Ecco come l'ho implementato.Il codice funziona da poco più di un anno e con più browser, quindi penso che sia abbastanza affidabile.Questo è basato su RFC2616 e osservando cosa e quando inviavano i vari browser.

Ecco lo pseudocodice:

server_etag = gen_etag_for_this_file(myfile)
etag_from_browser = get_header("Etag")

if etag_from_browser does not exist:
    etag_from_browser = get_header("If-None-Match")
if the browser has quoted the etag:
    strip the quotes (e.g. "foo" --> foo)

set server_etag into http header

if etag_from_browser matches server_etag
    send 304 return code to browser

Ecco uno snippet della logica del mio server che gestisce questo.

/* the client should set either Etag or If-None-Match */
/* some clients quote the parm, strip quotes if so    */
mketag(etag, &sb);

etagin = apr_table_get(r->headers_in, "Etag");
if (etagin == NULL)
    etagin = apr_table_get(r->headers_in, "If-None-Match");
if (etag != NULL && etag[0] == '"') {
    int sl; 
    sl = strlen(etag);
    memmove(etag, etag+1, sl+1);
    etag[sl-2] = 0;
    logit(2,"etag=:%s:",etag);
}   
... 
apr_table_add(r->headers_out, "ETag", etag);
... 
if (etagin != NULL && strcmp(etagin, etag) == 0) {
    /* if the etag matches, we return a 304 */
    rc = HTTP_NOT_MODIFIED;
}   

Se vuoi aiuto con la generazione di etag, pubblica un'altra domanda e tirerò fuori del codice che faccia anche questo.HTH!

Altri suggerimenti

Una risposta 304 Not Modified può derivare da una richiesta GET o HEAD con un'intestazione If-Modified-Since ("IMS") o If-Not-Match ("INM").

Per decidere cosa fare quando ricevi queste intestazioni, immagina di gestire la richiesta GET senza queste intestazioni condizionali.Determina quali sarebbero i valori delle intestazioni ETag e Last-Modified in quella risposta e usali per prendere una decisione.Si spera che tu abbia costruito il tuo sistema in modo tale che determinarlo sia meno costoso che costruire la risposta completa.

Se è presente un INM e il valore di tale intestazione è uguale al valore che inseriresti nell'ETag, rispondi con 304.

Se è presente un IMS e il valore della data in tale intestazione è successivo a quello che inseriresti in Last-Modified, rispondi con 304.

Altrimenti, procedi come se la richiesta non contenesse quelle intestazioni.

Per un approccio con il minimo sforzo alla parte 2 della tua domanda, scopri quali intestazioni (Expires, ETag e Last-Modified) puoi produrre facilmente e correttamente nella tua applicazione Web.

Per materiale di lettura consigliato:

http://www.w3.org/Protocols/rfc2616/rfc2616.html

http://www.mnot.net/cache_docs/

Dovresti inviare un 304 se il client ha dichiarato esplicitamente che potrebbe già avere la pagina nella sua cache.Questo è chiamato GET condizionale, che dovrebbe includere il file se-modificato-dal intestazione nella richiesta.

Fondamentalmente, questa intestazione della richiesta contiene una data a partire dalla quale il client dichiara di avere una copia nella cache.Dovresti controllare se il contenuto è cambiato dopo questa data e inviare un 304 in caso contrario.

Vedere http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25 per la relativa sezione della RFC.

Gestiamo anche risorse memorizzate nella cache, ma protette.Se invii/generi un'intestazione ETAg (che la sezione 13.3 della RFC 2616 consiglia DOVREBBE), il client DEVE utilizzarla in una richiesta condizionale (tipicamente in un'intestazione If-None-Match - HTTP_IF_NONE_MATCH).Se invii un'intestazione Last-Modified (di nuovo DEVI), dovresti controllare l'intestazione If-Modified-Since - HTTP_IF_MODIFIED_SINCE -.Se li invii entrambi, il client DOVREBBE inviarli entrambi, ma DEVE inviare l'ETag.Tieni inoltre presente che la convalida è definita semplicemente come il controllo delle intestazioni condizionali per verificarne la rigorosa uguaglianza rispetto a quelle che invieresti.Inoltre, solo un validatore forte (come un ETag) verrà utilizzato per le richieste con intervallo (dove viene richiesta solo una parte di una risorsa).

In pratica, poiché le risorse che stiamo proteggendo sono abbastanza statiche e un secondo di ritardo è accettabile, stiamo facendo quanto segue:

  1. Verificare se l'utente è autorizzato ad accedere alla risorsa richiesta

    In caso contrario, reindirizzali o invia una risposta 4xx a seconda dei casi.Genereremo risposte 404 a richieste che sembrano tentativi di hacking o tentativi palesi di eseguire una corsa di sicurezza.

  2. Confronta l'intestazione If-Modified-Since con l'intestazione Last-Modified che invieremo (vedi sotto) per una rigorosa uguaglianza

    Se corrispondono, invia una risposta 304 Non modificato e esci dall'elaborazione della pagina

  3. Crea un'intestazione Last-Modified utilizzando l'ora di modifica della risorsa richiesta

    Cerca il formato della data HTTP in RFC 2616

  4. Invia l'intestazione e il contenuto della risorsa insieme a un tipo di contenuto appropriato

Abbiamo deciso di evitare l'intestazione ETag poiché è eccessiva per i nostri scopi.Suppongo che potremmo anche usare semplicemente la data e l'ora come ETag.Se passassimo a un vero sistema ETag, probabilmente memorizzeremmo gli hash calcolati per le risorse e li utilizzeremmo come ETag.

Se le tue risorse sono generate dinamicamente, ad esempio dal contenuto del database, gli ETag potrebbero essere più adatti alle tue esigenze, poiché sono solo testo da popolare come ritieni opportuno.

per quanto riguarda il controllo della cache:

Non dovresti preoccuparti del controllo della cache durante la distribuzione, oltre a impostarlo su un valore ragionevole.Fondamentalmente comunica al browser e ad altre entità downstream (come un proxy) il tempo massimo che dovrebbe trascorrere prima che la cache esaurisca.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top