title: Is it fine if first response is private with AppCache (Symfony2)?
body: <p>I'm trying to use http caching. In my controller I'm setting a response as follows: </p>
  
  <pre><code>$response-&gt;setPublic();
  $response-&gt;setMaxAge(120);
  $response-&gt;setSharedMaxAge(120);
  $response-&gt;setLastModified($lastModifiedAt);
  </code></pre>
  
  <p><strong>dev mode</strong></p>
  
  <p>In dev environment first response is a 200 with following headers:</p>
  
  <pre><code>cache-control:max-age=120, public, s-maxage=120
  last-modified:Wed, 29 Feb 2012 19:00:00 GMT
  </code></pre>
  
  <p>For next 2 minutes every response is a 304 with following headers:</p>
  
  <pre><code>cache-control:max-age=120, public, s-maxage=120
  </code></pre>
  
  <p>This is basically what I expect it to be.</p>
  
  <p><strong>prod mode</strong></p>
  
  <p>In prod mode response headers are different. Note that in app.php I wrap the kernel in AppCache.</p>
  
  <p>First response is a 200 with following headers:</p>
  
  <pre><code>cache-control:must-revalidate, no-cache, private
  last-modified:Thu, 01 Mar 2012 11:17:35 GMT
  </code></pre>
  
  <p>So it's a private no-cache response.</p>
  
  <p>Every next request is pretty much what I'd expect it to be; a 304 with following headers:</p>
  
  <pre><code>cache-control:max-age=120, public, s-maxage=120
  </code></pre>
  
  <p><strong>Should I worry about it? Is it an expected behaviour?</strong> </p>
  
  <p><strong>What will happen if I put Varnish or Akamai server in front of it?</strong></p>
  
  <p>I did a bit of debugging and I figured that response is private because of last-modified header. HttpCache kernel <a href="https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php#L210">uses EsiResponseCacheStrategy</a> to update the cached response (<a href="https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php#L171">HttpCache::handle()</a> method). </p>
  
  <pre><code>if (HttpKernelInterface::MASTER_REQUEST === $type) {
      $this-&gt;esiCacheStrategy-&gt;update($response);
  }
  </code></pre>
  
  <p>EsiResponseCacheStrategy <a href="https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.php#L42">turns a response into non cacheable</a> if it uses either Last-Response or ETag (<a href="https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.php#L40">EsiResponseCacheStrategy::add()</a> method):</p>
  
  <pre><code>if ($response-&gt;isValidateable()) {
      $this-&gt;cacheable = false;
  } else {
      // ... 
  }
  </code></pre>
  
  <p><a href="https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Response.php#L407">Response::isValidateable()</a> returns true if Last-Response or ETag header is present.</p>
  
  <p>It results in <a href="https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.php#L62">overwriting the Cache-Control header</a> (<a href="https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.php#L55">EsiResponseCacheStrategy::update()</a> method):</p>
  
  <pre><code>if (!$this-&gt;cacheable) {
      $response-&gt;headers-&gt;set('Cache-Control', 'no-cache, must-revalidate');
  
      return;
  }
  </code></pre>
  
  <p>I asked this question on Symfony2 user group but I didn't get an answer so far: <a href="https://groups.google.com/d/topic/symfony2/6lpln11POq8/discussion">https://groups.google.com/d/topic/symfony2/6lpln11POq8/discussion</a></p>
  
  <p><strong>Update.</strong></p>
  
  <p>Since I no longer have access to the original code I tried to <a href="https://github.com/jakzal/symfony-standard/blob/cache/src/Acme/DemoBundle/Controller/DemoController.php#L62">reproduce the scenario with the latest Symfony standard edition</a>.</p>
  
  <p>Response headers are more consistent now, but still seem to be wrong. </p>
  
  <p>As soon as I set a <code>Last-Modified</code> header on the response, the first response made by a browser has a: </p>
  
  <pre><code>Cache-Control:must-revalidate, no-cache, private
  </code></pre>
  
  <p>Second response has an expected:</p>
  
  <pre><code>Cache-Control:max-age=120, public, s-maxage=120
  </code></pre>
  
  <p>If I avoid sending <code>If-Modified-Since</code> header, every request returns <code>must-revalidate, no-cache, private</code>.</p>
  
  <p>It doesn't matter if the request was made in <code>prod</code> or <code>dev</code> environment anymore.</p>