<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Performance web &#187; cache-control</title>
	<atom:link href="http://performance.survol.fr/avec/cache-control/feed/" rel="self" type="application/rss+xml" />
	<link>http://performance.survol.fr</link>
	<description>Quelques mots pour des sites web rapides</description>
	<lastBuildDate>Fri, 18 Jun 2010 12:47:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Experience de voici.fr</title>
		<link>http://performance.survol.fr/2009/11/experience-de-voici-fr/</link>
		<comments>http://performance.survol.fr/2009/11/experience-de-voici-fr/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 11:00:12 +0000</pubDate>
		<dc:creator>Éric</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[cache-control]]></category>
		<category><![CDATA[Charles-Christian Croix]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[dotclear]]></category>
		<category><![CDATA[ezPublish]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[images]]></category>
		<category><![CDATA[jpegtran]]></category>
		<category><![CDATA[mod_gzip]]></category>
		<category><![CDATA[pngcrush]]></category>
		<category><![CDATA[Voici.fr]]></category>

		<guid isPermaLink="false">http://performance.survol.fr/?p=763</guid>
		<description><![CDATA[J&#8217;aime bien apporter un peu de retours d&#8217;expérience, pour montrer que toute la théorie fonctionne aussi en pratique. Certes il y a Yahoo!, Google, Amazon, mais ce sont des trop gros sites pour que le développeur moyen se sente impliqué. &#8230; <a href="http://performance.survol.fr/2009/11/experience-de-voici-fr/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>J&#8217;aime bien apporter un peu de retours d&#8217;expérience, pour montrer que toute la théorie fonctionne aussi en pratique. Certes il y a Yahoo!, Google, Amazon, mais ce sont des trop gros sites pour que le développeur moyen se sente impliqué.</p>
<p>Alors voilà, Charles-Christian Croix nous parle un peu de ce qui a été réalisé sur Voici.fr. <a href="http://www.karlesnine.com/post/2009/10/12/Voici.fr-exemple-utilisation-des-caches-web-pour-un-site-eZ-Publish-4.2-optimisation-squid-reverse-proxy-mod_expires-mod_gzip">La première étape</a> se fait via une configuration des entêtes HTTP de cache de ezPublish puis une configuration de mod_gzip sur Apache, et enfin par une configuration de mod_expires, toujours sur Apache. Il fait de même plus tard <a href="http://www.karlesnine.com/post/2009/10/22/DC2">sur une installation Dotclear</a>.<span id="more-763"></span></p>
<p>On peut regretter l&#8217;expiration très courte (une journée) accompagniée d&#8217;un <code>must-revalidate</code>, mais je me permet d&#8217;insister avec intérêt sur le <a href="http://performance.survol.fr/2008/05/prive-ou-public/"><code>Cache-Control: public</code></a> très important dans le cas d&#8217;une application PHP. EzPublish utilise très probablement les sessions PHP, qui ajoutent par défaut un <code>Cache-Control: private</code>. il faut donc le corriger.</p>
<p>Dans un autre billet on voit <a href="http://www.karlesnine.com/post/2009/10/27/Voici.fr-Interet-de-l-optimisation-web-cache-et-des-performance-des-reverses-proxys">le résultat sur le squid</a> de la gestion du cache des images et de la compression HTTP :</p>
<p style="text-align: center;"><a href="http://performance.survol.fr/wp-content/uploads/2009/11/Squid.Conf.Effect.png"><img class="aligncenter size-full wp-image-765" title="Squid.Conf.Effect" src="http://performance.survol.fr/wp-content/uploads/2009/11/Squid.Conf.Effect.png" alt="La charge du proxy inverse diminue drastiquement à partir de juillet" width="597" height="269" /></a></p>
<p>Dans une seconde partie il nous parle de <a href="http://www.karlesnine.com/post/2009/10/23/Optimision-Image-pour-le-web">compression d&#8217;images</a>. Là aussi les solutions sont connues mais c&#8217;est appréciable de voir quelqu&#8217;un le mettre en œuvre et en parler ensuite. Sur les PNG il identifie un gain moyen d&#8217;un tiers pour le poids des images. C&#8217;est plus que conséquent, et ça aura un effet visible et sur le client et sur votre infrastructure. Je me permet juste d&#8217;apporter un bémol sur l&#8217;utilisation du paramètre <code>-brute</code> de pngcrush, qui est loin d&#8217;être le meilleur compromis gain/temps.</p>
]]></content:encoded>
			<wfw:commentRss>http://performance.survol.fr/2009/11/experience-de-voici-fr/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Petit point sur les caches</title>
		<link>http://performance.survol.fr/2009/06/petit-point-sur-les-caches/</link>
		<comments>http://performance.survol.fr/2009/06/petit-point-sur-les-caches/#comments</comments>
		<pubDate>Wed, 10 Jun 2009 10:00:39 +0000</pubDate>
		<dc:creator>Éric</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[cache-control]]></category>
		<category><![CDATA[expiration]]></category>
		<category><![CDATA[expires]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[proxy]]></category>

		<guid isPermaLink="false">http://performance.survol.fr/?p=515</guid>
		<description><![CDATA[Votre page peut-elle être mise en cache par le navigateur ? voyons ce qu&#8217;il en est en théorie avec HTTP 1.1 (en pratique le navigateur fera toujours ce qu&#8217;il veut, et il y a plus de couples navigateur/configuration que vous &#8230; <a href="http://performance.survol.fr/2009/06/petit-point-sur-les-caches/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Votre page peut-elle être mise en <a href="http://performance.survol.fr/2008/03/impact-du-cache-http/">cache</a> par le navigateur ? voyons ce qu&#8217;il en est en théorie avec <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html"><acronym title="hypertext transfer protocol" lang="en">HTTP</acronym> 1.1</a> (en pratique le navigateur fera toujours ce qu&#8217;il veut, et il y a plus de couples navigateur/configuration que vous ne l&#8217;imaginez, donc n&#8217;ayez aucune certitude).<span id="more-515"></span></p>
<h3>Les absolus</h3>
<p>Quoi que vous disiez, quoi que vous fassiez, si le serveur vous a répondu avec un code d&#8217;erreur 400, le navigateur devrait mettre en cache se résultat et ne pas refaire la même requête. C&#8217;est plutôt logique pour une requête que le serveur a considéré comme invalide.</p>
<p>Quoi que vous disiez, quoi que vous fassiez, si le code de retour était 303 ou 307, le navigateur ne devrait pas mettre en cache ce résultat. La redirection est temporaire, marquée comme telle, mettre en cache du temporaire c&#8217;est faire du permanent, donc contredire la réponse.</p>
<h3>L&#8217;heuristique</h3>
<p>S&#8217;il s&#8217;agit d&#8217;une requête de type <span lang="en">GET</span> avec un code de retour 200, 203, 206, 300, 301 ou 410, alors le navigateur ou le proxy sont encouragés à mettre en cache suivant leurs propres heuristiques. Le plus souvent la page HTML elle-même n&#8217;est pas mise en cache par défaut, mais les composants référencés par cette page sont mis en cache pour la durée de la session.</p>
<p>Il est à noter que la spécification HTTP 1.1 prévoit la fonctionnalité de retour arrière des navigateurs et incite le navigateur à réutiliser la page précédente sans la réactualiser, quand bien même elle aurait expiré. Le visiteur l&#8217;a déjà vu, il s&#8217;agit de lui représenter là où il était avant, pas de revenir sur la page actualisée.</p>
<h3>L&#8217;invalidation</h3>
<p>Quand le serveur répond à une requête <span lang="en">POST</span>, les versions en cache de cette <acronym title="uniform resource identifier" lang="en">URI</acronym> ou de celle dans les entêtes <code lang="en">Location</code> ou <code lang="en">Content-Location</code> doivent être effacés. Ceci implique immédiatement que par défaut une requête <span lang="en">POST</span> ne sera pas mise en cache.</p>
<p>La spécification HTTP 1.1 va même un peu plus loin en prenant en compte l&#8217;usage des paramètres de requêtes dans les URI. Certains utilisent ainsi des paramètres en <span lang="en">GET</span> pour réaliser des actions qui devraient être faites en <span lang="en">POST</span> (puisque provocant un changement dans l&#8217;entité résultat). Pour y palier, HTTP 1.1 demande à ce que ces requêtes (contenant un point d&#8217;interrogation dans le chemin) ne soient pas mises en cache quand bien même elles seraient faites avec le verbe <span lang="en">GET</span>.</p>
<p>Petite note : Si vous renvoyez un document avec une entête <code lang="en">Date</code> inférieure à celle qu&#8217;avait eu le navigateur la dernière fois, cette réponse ne devrait être pas mise en cache.</p>
<h3>La déclaration explicite</h3>
<p>Maintenant, hors les premiers cas absolus, les entêtes explicites ont priorité. Une <a href="http://performance.survol.fr/2008/05/prive-ou-public/">entête <code lang="en">Cache-Control</code></a> à <code lang="en">public</code>, <code lang="en">private</code>, ou <code lang="en">no-cache</code> change le comportement par défaut. Un <a href="http://performance.survol.fr/2008/10/expires-et-cache-control-une-date-limite-de-consommation-pour-vos-contenus/"><code lang="en">max-age</code> ou <code lang="en">Expires</code></a> impose un <code lang="en">cache</code> et un <code lang="en">must-revalidate</code> impose une revalidation, même si ces règles contredisent le comportement par défaut pour la ressource en question.</p>
<p>Enfin, les caches sont toujours dépendants de l&#8217;entête <code lang="en">Vary</code>, qui permet de restreindre le cache à un navigateur, ou des visteurs avec un certain cookie, etc.</p>
]]></content:encoded>
			<wfw:commentRss>http://performance.survol.fr/2009/06/petit-point-sur-les-caches/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Expires et Cache-Control, une date limite de consommation pour vos contenus</title>
		<link>http://performance.survol.fr/2008/10/expires-et-cache-control-une-date-limite-de-consommation-pour-vos-contenus/</link>
		<comments>http://performance.survol.fr/2008/10/expires-et-cache-control-une-date-limite-de-consommation-pour-vos-contenus/#comments</comments>
		<pubDate>Wed, 01 Oct 2008 10:00:47 +0000</pubDate>
		<dc:creator>Éric</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[cache-control]]></category>
		<category><![CDATA[expiration]]></category>
		<category><![CDATA[expires]]></category>
		<category><![CDATA[http]]></category>

		<guid isPermaLink="false">http://performance.survol.fr/?p=206</guid>
		<description><![CDATA[Je parle de détails et de ce que je rencontre dans mes lectures, et j&#8217;en oublie le principal. alors voilà, si vous ne devez retenir qu&#8217;une chose c&#8217;est d&#8217;utiliser des dates d&#8217;expiration explicites sur vos contenus. Il s&#8217;agit d&#8217;informer le &#8230; <a href="http://performance.survol.fr/2008/10/expires-et-cache-control-une-date-limite-de-consommation-pour-vos-contenus/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Je parle de détails et de ce que je rencontre dans mes lectures, et j&#8217;en oublie le principal. alors voilà, si vous ne devez retenir qu&#8217;une chose c&#8217;est d&#8217;<strong>utiliser des dates d&#8217;expiration explicites</strong> sur vos contenus.</p>
<p>Il s&#8217;agit d&#8217;informer le navigateur que votre contenu est valable pendant une certaine durée. Cela peut être dix minutes, une heure, un jour, un mois, ou plusieurs années. Tant que cette durée n&#8217;a pas expirée, le navigateur sait que son contenu est à jour, il peut donc éviter de le retélécharger. Vous gagnez du temps en évitant la requête HTTP et vous laissez de la place pour d&#8217;autres téléchargements. Au lieu de prendre une demi seconde, votre contenu sera lu quasiment instantanément.<span id="more-206"></span></p>
<h3>Les détails HTTP 1.0</h3>
<p>En fait tout ça c&#8217;est assez simple. En <a href="http://www.w3.org/Protocols/HTTP/1.0/spec.html">HTTP 1.0</a>, le serveur envoie avec le contenu une <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.21">entête Expires</a> avec une date au format de la <a href="http://www.freesoft.org/CIE/RFC/1123/">RFC 1123</a>.</p>
<pre>Expires: Thu, 01 Dec 1994 16:00:00 GMT</pre>
<p>Le navigateur et les proxy stockent dans le cache la ressource avec cette date. Les prochaines fois c&#8217;est le contenu sauvegardé dans le cache qui est utilisé, sans aucun appel au serveur.</p>
<p>Une fois la date dépassée, le navigateur fait de nouveau appel au serveur pour obtenir un contenu mis à jour, et éventuellement une nouvelle date d&#8217;expiration explicite. C&#8217;est normalement une requête conditionnelle qui est faite à ce niveau là donc si le contenu n&#8217;a toujours pas changé il ne sera toujours pas retéléchargé inutilement.</p>
<h3>Les détails HTTP 1.1</h3>
<p>Le gros défaut HTTP 1.0 c&#8217;est qu&#8217;en général on ne souhaite pas une date d&#8217;expiration fixe, on cherche une expiration de type « maintenant + 10 jours ». Résultat, il faut générer la date à chaque fois.</p>
<p><a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">HTTP 1.1</a> nous propose un mécanisme plus sympathique avec <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9">l&#8217;entête Cache-Control</a> dont je vous avais détaillé un des paramètres il y a quelques temps. Le paramètre qui nous intéresse ici est <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.3">le paramètre max-age</a>. Il prend un nombre de secondes pendant lesquelles le contenu doit être considéré comme à jour.</p>
<pre>Cache-Control: public;max-age=3600</pre>
<p>Cette directive est valable autant pour les caches partagés (proxy) que les caches personnels (navigateur). Il existe toutefois un second <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.3">paramètre s-maxage</a>, qui ne cible que les caches partagés. Le fonctionnement est similaire.</p>
<h3>J&#8217;utilise quoi ?</h3>
<p>Autant que possible, utilisez les deux. Rien n&#8217;est parfait dans ce bas monde et vous n&#8217;avez pas de garantie que la directive Cache-Control sera interprétée correctement, même si le client utilise la version 1.1 du protocole.</p>
<p>En cas de conflit le client est censé utiliser la directive Cache-Control. Mais après tout, pourquoi voudriez-vous envoyer deux informations contradictoires ?</p>
<h3>Comment ?</h3>
<p>Le plus simple sous Apache c&#8217;est <a href="http://httpd.apache.org/docs/2.0/mod/mod_expires.html">mod_expires</a>. Vous pouvez régler le comportement par défaut et par type de fichier. À chaque fois vous pouvez définir une durée pendant laquelle le contenu est considéré comme à jour, et si cette durée est à prendre à partir de la dernière modification de votre contenu ou de la date de la requête.</p>
<pre>ExpiresDefault "access plus 1 month 15 days 2 hours"
ExpiresByType image/gif "modification plus 5 hours 3 minutes"</pre>
<p><a href="http://trac.lighttpd.net/trac/wiki/Docs%3AModExpire">Pour Lighttpd le module a le même nom</a>, et la syntaxe est assez similaire :</p>
<pre class="last literal-block">$HTTP["url"] =~ "^/images/" {
     expire.url = ( "" =&gt; "access 1 hours" )
}</pre>
<h3>Sur quoi ?</h3>
<p>Ces entêtes sont pertinentes pour tout ce qui bouge peu, pas du tout, ou à une fréquence déterminée :</p>
<p>Prenez en compte au moins vos logos, vos icônes, vos images de fond, bref, ce qui ne change quasiment jamais, sans exception. Pour ces contenus vous pouvez mettre une expiration virtuellement infinie, de plusieurs années. Le jour où vous faites une modification il suffira de faire un nouveau fichier avec une nouvelle adresse publique.</p>
<p>Pour vos feuilles de style et vos javascript, même chose. Vos contenus changent plus souvent mais si vous arrivez à changer l&#8217;URL à chaque modification vous pouvez encore mettre une expiration quasi infinie. Pour changer l&#8217;adresse à chaque version vous pouvez ajouter le numéro de version dans le nom du fichier, ou ajouter un paramètre à l&#8217;url qui contient la date de dernière modification. Je ferai un billet plus complet sur le sujet plus tard.</p>
<p>Enfin, les pages HTML. Là il faut être plus fin. Toutes les pages ne sont pas pertinentes pour une expiration. Plus classiquement si à deux minutes d&#8217;intervalle il est important que le contenu change, oubliez l&#8217;expiration explicite. Par contre une bonne partie des pages peuvent avoir une expiration de quelques minutes, voire d&#8217;une ou deux heures. C&#8217;est souvent le cas des pages d&#8217;accueil et des pages principales. L&#8217;utilisateur y revient souvent lors de sa navigation. Si ces pages peuvent être instantanées, c&#8217;est un réel gain pour l&#8217;utilisateur. Si vous avez un système d&#8217;authentification sur vos pages, n&#8217;oubliez pas de <a href="http://performance.survol.fr/2008/05/prive-ou-public/">déclarer aussi le cache comme privé avec la directive Cache-Control</a>.</p>
<h3>Le bénéfice</h3>
<p>Un contenu avec une expiration explicite c&#8217;est un contenu qu&#8217;on évite de retélécharger plusieurs fois inutilement. Pour l&#8217;utilisateur c&#8217;est la sensation que le téléchargement est instantané, que l&#8217;interface et que le site réagissent immédiatement — et n&#8217;oubliez pas, <a href="http://performance.survol.fr/2008/06/a-quoi-ca-sert/">cela a une influence importante sur votre business</a>. Pour vous c&#8217;est autant de charge en moins pour votre serveur, et autant de bande passante économisée. Rien que là dessus vous pouvez économiser des sommes importantes.</p>
<p>Pour exemple, la page de Yahoo! met environ deux secondes tout compris à charger avec plus de 40 requêtes HTTP, ce qui en soit est assez honorable face au reste du web. Par contre sur cette quarantaine de requêtes HTTP, plus des trois quarts ont une expiration explicite comme détaillé plus haut. Le résultat c&#8217;est que ma seconde visite ne télécharge plus que 7 composants externes. Ma bande passante est libre pour autre chose et ma page se charge bien plus rapidement. Suivant les publicités sur la page, c&#8217;est entre une demi seconde et une seconde que je gagne. Pour une page d&#8217;accueil qui ne doit surtout pas donner une impression de lenteur, c&#8217;est significatif et même important.</p>
]]></content:encoded>
			<wfw:commentRss>http://performance.survol.fr/2008/10/expires-et-cache-control-une-date-limite-de-consommation-pour-vos-contenus/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Privé ou public ?</title>
		<link>http://performance.survol.fr/2008/05/prive-ou-public/</link>
		<comments>http://performance.survol.fr/2008/05/prive-ou-public/#comments</comments>
		<pubDate>Tue, 27 May 2008 10:59:18 +0000</pubDate>
		<dc:creator>Éric</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[cache-control]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[proxy]]></category>

		<guid isPermaLink="false">http://performance.survol.fr/?p=33</guid>
		<description><![CDATA[La directive Cache-Control est une vrai mine d&#8217;or pour la gestion du cache, au risque même de faire un peu fourre-tout. Aujourd&#8217;hui je m&#8217;intéresse surtout aux notions de document public et de document privé. Visibilité et autorisation de cache Pour &#8230; <a href="http://performance.survol.fr/2008/05/prive-ou-public/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>La directive <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9"><code>Cache-Control</code></a> est une vrai mine d&#8217;or pour la gestion du cache, au risque même de faire un peu fourre-tout. Aujourd&#8217;hui je m&#8217;intéresse surtout aux <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1">notions de document public et de document privé</a>.</p>
<h3>Visibilité et autorisation de cache</h3>
<p>Pour faire court, cette directive contient quatre paramètres de visibilité : <code>public</code>, <code>private</code>, <code>no-cache</code> et <code>no-store</code>.<span id="more-28"></span></p>
<ul>
<li>La valeur <code>no-cache</code> est assez simple : Les navigateurs et proxys ne doivent pas réutiliser le document reçu sans faire une nouvelle validation sur le serveur.</li>
<li>La valeur <code>private</code> impose aux cache partagés (les proxys) de ne pas mettre en cache la page, mais autorise les caches privés (navigateurs) à utiliser un cache sur le document.</li>
<li>La valeur <code>public</code> autorise explicitement le cache quel que soit les autres paramètres et le comportement normal sur ce document.</li>
<li>Enfin, la valeur <code>no-store</code> demande aux caches de ne stocker le message ni de manière permanente ni en mémoire volatile.</li>
</ul>
<h3>Les subtilités</h3>
<p>On a l&#8217;impression d&#8217;une simple hiérarchie qui va de &laquo;&nbsp;pas de cache&nbsp;&raquo; à &laquo;&nbsp;cache partout&nbsp;&raquo; en passant par l&#8217;intermédiaire &laquo;&nbsp;cache privé&nbsp;&raquo;. Malheureusement les détails sont plus complexes que ça.</p>
<p>Le serveur proxy de votre entreprise pourra accélérer le téléchargement d&#8217;un document en <code>no-cache</code>. L&#8217;astuce c&#8217;est que contrairement à ce que le nom laisse entendre, le cache n&#8217;est pas interdit. On impose juste au serveur de revalider le document avec une requête conditionnelle <code>if-modified-since</code> ou <code>if-none-match</code>. Le document sera quand même dans le cache partagé, et si vous gérez mal les requêtes conditionnelles il pourra être partagé entre plusieurs utilisateurs différents. À l&#8217;inverse, un document marqué comme <code>private</code> ne pourra pas, lui, être accéléré par le proxy partagé car c&#8217;est directement la notion de cache qui y est prohibée. Troublant non ?</p>
<p>C&#8217;est <code>no-store</code> qui interdit le stockage, que ce soit sur disque ou en mémoire (et empêche donc les requêtes conditionnelles par la suite). Par contre ce <code>no-store</code> n&#8217;interdit pas formellement le cache. Si un proxy recevait une seconde requête similaire avant de recevoir la réponse à la première, il pourrait techniquement servir la même réponse aux deux clients tout en se conformant aux spécifications. Bref, on ne peut pas stocker mais on peut toujours partager les réponses sur un proxy commun. Je doute qu&#8217;un seul proxy sur le marché fasse de telles optimisations qui &laquo;&nbsp;sonnent faux&nbsp;&raquo;, mais à défaut c&#8217;est un <code>Cache-Control: no-cache, no-store</code> qu&#8217;il faut utiliser (oui, on peut cumuler).</p>
<p>La valeur <code>public</code> pose moins de contre-sens mais cela ne veut pas dire qu&#8217;elle soit forcément bien comprise elle aussi. Elle n&#8217;implique pas uniquement que le document est public, donc potentiellement mis en cache partout. Cette valeur autorise aussi un cache là où il n&#8217;aurait pas été autorisé autrement. Ainsi une requête <code>POST</code> avec un résultat <code>public</code> pourra utiliser le cache. Votre formulaire de contact est public, vous avez réglé naïvement le <code>Cache-Control</code> à <code>public</code> (après tout, il n&#8217;est pas privé ce formulaire), et voilà que si deux personnes utilisent le formulaire à partir de la même entreprise le second aura le message de confirmation mais son message ne sera pas envoyé. Gênant non ? Même chose si vous mettez en place une authentification <acronym title="hypertext transfer protocol">HTTP</acronym> cumulée avec un <code>Cache-Control: public</code>, vous risquez d&#8217;avoir des utilisateurs non autorisés sur le site.</p>
<p>Bref, pas grand chose d&#8217;intuitif et il faut faire attention aux détails.</p>
<h3>D&#8217;autres problèmes</h3>
<p>Du coup, conséquence directe de ces subtilités, la valeur par défaut n&#8217;est ni <code>public</code>, ni <code>private</code>, ni <code>no-cache</code> et encore moins <code>no-store</code>. Par défaut il n&#8217;y a rien et on ne peut rien préciser pour forcer explicitement le comportement &laquo;&nbsp;sain&nbsp;&raquo; par défaut.</p>
<p>C&#8217;est d&#8217;autant plus gênant avec <acronym title="php hypertext preprocessos">PHP</acronym>. Ce dernier ajoute automatiquement un <code>Cache-Control: no-cache</code> à toutes les réponses si une session est utilisée sur la page. Les frameworks modernes en PHP ouvrent la session par défaut, la conséquence c&#8217;est que toutes les pages sont d&#8217;un coup interdites de partage, même les pages publiques. Il ne vous reste plus qu&#8217;à réécrire manuellement les entêtes <code>Cache-Control</code>, <code>Pragma</code> et <code>Expires</code> (oui, les trois, PHP ne fait pas dans la dentelle). PHP mérite un billet à part entière, donc je ne m&#8217;étendrai pas plus dessus pour l&#8217;instant.</p>
<p>Pour ne rien arranger Microsoft Internet Explorer a <a href="http://support.microsoft.com/kb/812935">un problème</a> avec le téléchargement de certains fichiers sur HTTPS quand le <code>Cache-Control</code> est à <code>no-cache</code> ou <code>no-store</code> (il interprête les deux de la même façon, traitant no-cache comme un no-store). Il refuse alors le stockage temporaire du fichier et ne permet donc pas son ouverture avec une application tierce (traitement de texte par exemple). Bref, même si c&#8217;est malheureux pour l&#8217;efficacité des proxy, il vaut souvent mieux cumuler un <code>Cache-Control: private</code> avec un paramètre tiers pour forcer la revalidation que d&#8217;utiliser <code>no-cache</code>. Et pour ceux qui suivent bien ça veut dire que télécharger une pièce jointe via https à partir d&#8217;une application PHP qui utilise les sessions, ça posera un problème si vous ne bidouillez pas <a href="http://uk3.php.net/manual/fr/function.session-cache-limiter.php"><code>session_cache_limiter()</code></a>.</p>
<h3>Rapidement</h3>
<p>Pour récapituler, la règle de base c&#8217;est donc : <strong>ne rien préciser sur les parties publiques du site et indiquer <code>private</code> sur les parties privées</strong> (et uniquement celles ci car ça désactive tous les proxys partagés).</p>
<p>La valeur <code>public</code> est à éviter ou utiliser avec précautions car elle risque de mettre en cache des requêtes qui ne le devraient pas ; la valeur <code>no-cache</code> permettra à vos documents privés de se retrouver sur des caches partagés tout en posant des problèmes pour les téléchargements de fichiers par HTTPS, et la valeur <code>no-store</code> ne garantit pas l&#8217;absence de cache commun tout en ayant les mêmes problèmes de téléchargement.</p>
<h3>Plus loin</h3>
<p>En allant un peu plus loin on peut même voir que le <code>private</code> et le <code>no-cache</code> peuvent avoir un paramètre. Il s&#8217;agit de définir précisément quel champ de la réponse ou de la requête doit être considéré comme privé ou ne doit pas être mis en cache. Je n&#8217;ai jamais vu ces paramètres utilisés et je ne vois pas comment ils pourraient l&#8217;être (pour revalider un des champs il faut de fait relancer toute la requête donc ça revient à appliquer le <code>private</code> ou le <code>no-cache</code> sur l&#8217;ensemble du message). Si quelqu&#8217;un voit comment ça pourrait être utilisé, qu&#8217;il n&#8217;hésite pas à commenter.</p>
]]></content:encoded>
			<wfw:commentRss>http://performance.survol.fr/2008/05/prive-ou-public/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
