Question

J'écris une méthode de gestion des ressources dans laquelle je contrôle l'accès à divers fichiers et j'aimerais pouvoir utiliser le cache du navigateur.Ma question est double :

  1. Quels sont les en-têtes HTTP définitifs que je dois vérifier pour savoir avec certitude si je dois envoyer une réponse 304, et qu'est-ce que je recherche lorsque je les vérifie ?

  2. De plus, y a-t-il des en-têtes que je dois envoyer lorsque j'envoie initialement le fichier (comme « Last-Modified ») en réponse 200 ?

Un pseudo-code serait probablement la réponse la plus utile.


Qu’en est-il de l’en-tête cache-control ?Les différentes valeurs possibles de cela peuvent-elles affecter ce que vous envoyez au client (à savoir l'âge maximum) ou ne doivent-elles être respectées que si elles sont modifiées depuis ?

Était-ce utile?

La solution

Voici comment je l'ai implémenté.Le code fonctionne depuis un peu plus d'un an et avec plusieurs navigateurs, donc je pense qu'il est assez fiable.Ceci est basé sur RFC2616 et en observant ce que et quand les différents navigateurs envoyaient.

Voici le pseudocode :

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

Voici un extrait de la logique de mon serveur qui gère cela.

/* 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;
}   

Si vous voulez de l'aide avec la génération etag, posez une autre question et je vais trouver du code qui fait cela également.HTH!

Autres conseils

Une réponse 304 Not Modified peut résulter d'une requête GET ou HEAD avec un en-tête If-Modified-Since (« IMS ») ou If-Not-Match (« INM »).

Afin de décider quoi faire lorsque vous recevez ces en-têtes, imaginez que vous gérez la requête GET sans ces en-têtes conditionnels.Déterminez quelles seraient les valeurs de vos en-têtes ETag et Last-Modified dans cette réponse et utilisez-les pour prendre la décision.J'espère que vous avez construit votre système de telle sorte que déterminer cela soit moins coûteux que de construire la réponse complète.

S'il existe un INM et que la valeur de cet en-tête est la même que la valeur que vous placeriez dans l'ETag, répondez par 304.

S'il existe un IMS et que la valeur de date dans cet en-tête est ultérieure à celle que vous placeriez dans Last-Modified, répondez par 304.

Sinon, procédez comme si la requête ne contenait pas ces en-têtes.

Pour une approche simplifiée de la partie 2 de votre question, déterminez lequel des en-têtes (Expires, ETag et Last-Modified) vous pouvez facilement et correctement produire dans votre application Web.

Pour des suggestions de lecture :

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

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

Vous devez envoyer un 304 si le client a explicitement déclaré qu'il avait peut-être déjà la page dans son cache.C'est ce qu'on appelle un GET conditionnel, qui doit inclure le si-modifié-depuis en-tête dans la requête.

Fondamentalement, cet en-tête de requête contient une date à partir de laquelle le client prétend disposer d'une copie en cache.Vous devez vérifier si le contenu a changé après cette date et envoyer un 304 si ce n'est pas le cas.

Voir http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25 pour la section correspondante dans la RFC.

Nous gérons également des ressources mises en cache, mais sécurisées.Si vous envoyez/générez un en-tête ETAg (ce que la section 13.3 de la RFC 2616 vous recommande DE DEVRAIENT), alors le client DOIT l'utiliser dans une requête conditionnelle (généralement dans un en-tête If-None-Match - HTTP_IF_NONE_MATCH -).Si vous envoyez un en-tête Last-Modified (encore une fois, vous DEVRIEZ), alors vous devez vérifier l'en-tête If-Modified-Since - HTTP_IF_MODIFIED_SINCE -.Si vous envoyez les deux, alors le client DEVRAIT envoyer les deux, mais il DOIT envoyer l'ETag.Notez également que la validation est simplement définie comme la vérification des en-têtes conditionnels pour une stricte égalité par rapport à ceux que vous enverriez.De plus, seul un validateur puissant (tel qu'un ETag) sera utilisé pour les requêtes à distance (où seule une partie d'une ressource est demandée).

En pratique, étant donné que les ressources que nous protégeons sont assez statiques et qu'un délai d'une seconde est acceptable, nous procédons comme suit :

  1. Vérifiez si l'utilisateur est autorisé à accéder à la ressource demandée

    Si ce n'est pas le cas, redirigez-les ou envoyez une réponse 4xx, le cas échéant.Nous générerons 404 réponses aux requêtes qui ressemblent à des tentatives de piratage ou à des tentatives flagrantes d’exécution d’une opération de sécurité.

  2. Comparez l'en-tête If-Modified-Since à l'en-tête Last-Modified que nous enverrions (voir ci-dessous) pour une stricte égalité

    S'ils correspondent, envoyez une réponse 304 Non modifié et quittez le traitement de la page.

  3. Créer un en-tête Last-Modified en utilisant l'heure de modification de la ressource demandée

    Recherchez le format de date HTTP dans la RFC 2616

  4. Envoyez l'en-tête et le contenu de la ressource avec un type de contenu approprié

Nous avons décidé d'éviter l'en-tête ETag car il est excessif pour nos besoins.Je suppose que nous pourrions également simplement utiliser l'horodatage comme ETag.Si nous passons à un véritable système ETag, nous stockerions probablement les hachages calculés pour les ressources et les utiliserions comme ETags.

Si vos ressources sont générées dynamiquement, à partir, par exemple, du contenu d'une base de données, alors les ETags peuvent être mieux adaptés à vos besoins, car ce ne sont que du texte à remplir comme bon vous semble.

concernant le contrôle du cache :

Vous ne devriez pas avoir à vous soucier du contrôle du cache lors du service, à part le définir sur une valeur raisonnable.Il s'agit essentiellement d'indiquer au navigateur et aux autres entités en aval (telles qu'un proxy) le temps maximum qui doit s'écouler avant l'expiration du cache.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top