Qu’est ce qu’une 304 ?
Une 304 c’est un code retourné par le serveur web pour afficher la page de votre navigateur beaucoup plus rapidement qu’un code 200. Ce code envoie simplement au navigateur la date de dernière modification. Lors de la 1er visite, vous aurez le code 200, puis à la 2e visite, si la page n’a pas été modifiée, alors votre navigateur affichera instantanément la page demandée avec une 304. Vous voulez voir ce que ça donne en temps réel, alors testez cet exemple. Pour bien vous montrer la différence de vitesse, celui ci va chercher le contenu de 100 fichiers texte pour les afficher. Au lieu de faire 100 requêtes curl, vous n’en aurez aucune ! En condition de page réel (une page produit par ex), les performances sont bien évidemment plus minimes.
Pour pouvoir réaliser une 304, vous avez 2 moyens. Voyons ensemble comment ça se passe.
last_modified_time et HTTP_IF_MODIFIED_SINCE
Ici, vous indiquez la date de dernière modification. Dans cet exemple, on prend la date de modification d’un fichier (sous Windows le filemtime ne fonctionne pas, il vous faudra trouver une autre source pour la date).
$last_modified_time = filemtime($file); // always send headers header("Last-Modified: ".gmdate("D, d M Y H:i:s", $last_modified_time)." GMT"); // exit if not modified if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time) { header("HTTP/1.1 304 Not Modified"); exit; }
Etag et HTTP_IF_NONE_MATCH
Ici, on va donner un hash du fichier demandé (plutôt qu’une date) , et le comparer à celui déjà envoyé.
$etag = md5_file($file); // always send headers header("Etag: $etag"); // exit if not modified if (@trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) { header("HTTP/1.1 304 Not Modified"); exit; }
Ca marche avec quels serveurs ?
Apache , nGinx, et même Varnish et surement aussi les autres. Pour Varnish faites attention, il faut être très rigoureux vis à vis de la date qu’on lui fournit.
Ex: If-Modified-Since: Wed, 15 Feb 2012 07:25:00 CET
Est faux, car ce n’est pas une date GMT, alors qu’avec Apache qui est plus souple, cela ne pose pas de problème.
Pourquoi dans certains cas les variables $_SERVER[‘HTTP_IF_NONE_MATCH’] ou $_SERVER[‘HTTP_IF_MODIFIED_SINCE’] sont-elles indéfinies (undefined) ?
Ces variables requiert le module Apache suivant: mod_headers.
Parfois, en fin de fichier .htaccess, on peut également vous demander d’ajouter ces lignes. Ne le faites pas, cela peut vous ajouter la variable, mais pas forcément la remplir.
Du coup, à quoi bon rajouter des variables si celles-ci sont nulles.
RewriteRule .* – [E=HTTP_IF_MODIFIED_SINCE:%{HTTP:If-Modified-Since}]
RewriteRule .* – [E=HTTP_IF_NONE_MATCH:%{HTTP:If-None-Match}]
D’autres blocages peuvent se produire à cause du .htaccess à la racine du site. En effet certaines directives du type Header unset Cache-Control, Header unset ETag peuvent supprimer vos variables de date mise en cache.
Pour refaire des tests, faites un control + F5 afin de ne pas prendre en compte le cache et repartir en code 200.
Pourquoi mes requêtes continuent-elles d’être toutes en code 200 ?
Attention à l’outil que vous utilisez pour vérifier votre code status. Les différents plugins Chrome / Firefox tel que HTTP Headers, ou encore Redirect Path ne font pas attention à ce code et vont pointer l’url comme si elle était appelée par un navigateur sans cache. Elle vous affichera donc un 200 alors que l’inspecteur réseau (F12) vous affichera bien le code 304. A noter que ce code ne sera valide que sur le contenu PHP et pas sur les différentes ressources (images, css, js…).
Est ce que cela fonctionne avec SSL / HTTPS ?
Oui cela fonctionne, mais attention, la moindre erreur dans votre certificat, et cela empêchera le cache de fonctionner. Si vous rencontrez des problèmes, vérifiez que ça fonctionne en HTTP, puis validez bien que votre certificat n’a pas de problème, ou qu’aucune ligne du htaccess n’entrave la procédure.
Pourquoi personne ne le fait ?
Cette recommandation n’est pas si simple à mettre en place. La documentation sur les problèmes rencontrés est faible tout comme la connaissance de cette technique. Et chez certains hébergeurs vous n’aurez pas les modules nécessaires (OVH mutualisé). De plus, si vous avez déjà un système de cache, alors vous ne gagnerez pas forcément grand chose (car cette optimisation ne s’applique qu’au code PHP); alors que si vous appliquer mal cette technique, vous pourrez perdre beaucoup. Imaginez, que vous afficher une page blanche à la place de la page demandée au moment de ré-afficher la page. Ca ne se verra pas au 1er coup d’oeil, mais lorsque Google repassera, il se posera la question « cette page est devenue vide, dois-je désindexer son contenu ? ».