Pourquoi Apache envoie-t-il 200 OK alors que Last-modified correspond à If-modified-since?

10

J'essaie d'avoir un comportement de base concernant ma stratégie de mise en cache: les fichiers doivent être mis en cache et revalidés avec le serveur à chaque fois. Je voudrais donc qu'Apache envoie un 304.

Voici la boîte de dialogue qui se produit pour chaque actualisation du navigateur:

Status Code:200 OK

Request Headers

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip,deflate,sdch
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control:max-age=0
Connection:keep-alive
Cookie: ...
Host:...
If-Modified-Since:Tue, 14 Oct 2014 15:10:37 GMT
If-None-Match:"1461-505636af08fcd-gzip"
User-Agent:Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36

Response Headers

Accept-Ranges:bytes
Cache-Control:No-cache
Connection:Keep-Alive
Content-Encoding:gzip
Content-Length:1412
Content-Type:text/html
Date:Tue, 14 Oct 2014 16:58:05 GMT
ETag:"1461-505636af08fcd-gzip"
Keep-Alive:timeout=5, max=99
Last-Modified:Tue, 14 Oct 2014 15:10:37 GMT
Server:Apache/2.4.6 (Ubuntu)
Vary:Accept-Encoding

(ceci provient de chrome devtools, avec Disable cache unchecked)

Vous pouvez voir que la réponse contient le Cache-Control: No-cache Header et que l'en-tête If-modified-since correspond au Last-modified. L'ETag correspond également.

Apache ne devrait-il pas envoyer un 304 dans ce cas?

ÉDITER

Désactiver ETags dans Apache avec

 Header  unset ETag

rend le comportement de mise en cache plus prévisible ...

zrz
la source
Je pense que Cache-Control:max-age=0le cache a été désactivé, vous voyez donc la Cache-Control:No-cacheréponse.
ThoriumBR
J'ai explicitement défini Cache-Control: No-cache dans ma configuration apache car à partir de w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1 , je comprends que cela provoque une revalidation pour chaque demande. La revalidation implique-t-elle de renvoyer le fichier? Je dirais qu'il devrait utiliser If-modified-since pour déterminer s'il s'agit d'un 200 ou d'un 304.
zrz

Réponses:

8

Cela semble être un vieux bug , expliquant pourquoi cela Header unset ETagfait une différence.

Apache 2.4.0+ ajoute automatiquement le nom de la méthode de compression à l'ETag (comme vu dans vos en-têtes) et empêche une réponse 304.

Les dernières versions de mod_deflate prennent en charge un DeflateAlterETag qui peut être utilisé pour contrôler ce comportement:

DeflateAlterETag NoChange
Mathias R. Jessen
la source
3
C'est correct mais Apache 2.4 ne contient pas cette option, seulement Apache 2.5. Cependant, personnellement, je ne trouve pas les ETags utiles car Apache les base sur la dernière date modifiée, plutôt que sur le contenu du fichier. La désactivation des ETags revient donc à l'en-tête If-Modified-Since, qui est basé sur la dernière date de modification de toute façon. Vous pouvez modifier l'ETag dans Apache pour le rendre basé sur la taille, la dernière modification et / ou l'inode - avec la taille et la dernière modification étant la valeur par défaut - mais, jusqu'à ce qu'ils ajoutent une option pour calculer un ETag en fonction de la somme de contrôle du contenu du fichier, son d'une utilisation limitée à mon humble avis. Je les éteins donc.
Barry Pollard
1
@BazzaDP Cela a du sens. 2.5 a également une DeflateAlterETag Removeoption pour faire exactement cela
Mathias R. Jessen
0

Celui-ci se démarque dans la demande comme étant un peu étrange:

Cache-Control:max-age=0

Probablement plus important cependant, je remarque que le contenu renvoyé est html. Est-il généré dynamiquement? Apache PEUT envoyer une réponse 304, mais à moins que vous ne fournissiez du contenu statique, ce n'est pas le travail d'Apache de faire cet appel, et cela se résume à la logique de votre application. Par exemple, la plupart des applications php ont un support limité pour de telles choses.

Un cache frontal peut être utile, car l'application de mise en cache peut vérifier l'heure de modification, etag, etc., mais uniquement si l'application et les en-têtes de demande sont compatibles avec le cache. Par exemple, l'application doit définir des en-têtes appropriés pour indiquer que le contenu peut être mis en cache, et des éléments comme l'en-tête de contrôle du cache dans votre demande annuleront le cache. Vos en-têtes ne semblent pas compatibles avec le cache.

mc0e
la source
Le fichier demandé est un fichier html statique, pour lequel Apache obtient le bon moment de modification. (Dernière mise à jour: Tue, 14 oct 2014 15:10:37 GMT). l'en-tête max-age = 0 est dans la demande envoyée par chrome lorsque je tape l'URL et appuie sur Entrée. Est-ce là à cause des réponses précédentes?
zrz
J'ai lu que Chrome ajoute automatiquement Cache-Control: max-age = 0 à la demande (sauf pour la première fois que vous chargez Chrome, tapez l'URL, appuyez sur Entrée). Mais cela ne semble pas affecter les autres serveurs (les CDN envoient 304 même avec max-age = 0 dans la demande).
zrz
@zrz: limiter la mise en cache intermédiaire est très utile lors du débogage, mais sinon cela nuirait aux performances. Vérifiez le contexte de ce que vous lisez sur ce que fait Chrome. En termes de ce qu'apache fait, c'est assez configurable. Cache-control est une instruction pour les caches intermédiaires, pas pour le serveur d'origine. Cependant, apache peut agir comme un cache intermédiaire et peut être configuré pour faire toutes sortes de choses. Je pense que si vous retirez vos instructions anti-mise en cache, vous obtiendrez un comportement plus semblable à ce que vous attendez d'un serveur d'origine.
mc0e
0

Si Apache est configuré avec Cache-Control:No-cache, Apache n'enverra jamais de message HTTP 304 Not modifiedau client.

Si vous souhaitez revalider certaines demandes, mettez un Cache-Control:No-cacheuniquement sur les pages où vous en avez besoin. Vous n'avez pas besoin de revalider toutes les ressources et vous gaspillez de la bande passante en le faisant.

ThoriumBR
la source
Il me semble que le terme "revalider" est confus. Pour moi, cela signifie vérifier s'il s'agit d'un 304. Ai-je tort?
zrz
Vous avez tort. Revalider consiste à renvoyer toutes les données au client et à le forcer à tout relire, même s'il possède déjà les mêmes informations. Vous désactivez essentiellement le cache sur chaque client.
ThoriumBR
Ça explique beaucoup. La dernière chose que j'ai besoin d'expliquer en gardant cela à l'esprit est qu'Apache envoie 304 pour certaines ressources (png par exemple), alors que j'ai toujours que Cache-Control ne définit aucun no-cache dans la réponse et à max-age = 0 dans la demande. Un indice?
2014
@ThoriumBR Si je vous ai bien interprété, vos deux réponses sont incorrectes ici; no-cache (par opposition à no-store) ne signifie pas «ne pas mettre en cache» et peut entraîner un 304 si le contenu n'a pas changé. En effet, l'OP s'y attendait mais ne l'a pas obtenu en raison du problème etag. must-revalidate concerne la façon dont le contenu périmé est géré et n'envoie pas toujours "les données à nouveau".
Nick