HttpCache does not consider ESI resources in HEAD requests
This commit is contained in:
parent
3b42d8859e
commit
4dd0e53171
|
@ -633,14 +633,6 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
|||
*/
|
||||
private function restoreResponseBody(Request $request, Response $response)
|
||||
{
|
||||
if ($request->isMethod('HEAD') || 304 === $response->getStatusCode()) {
|
||||
$response->setContent(null);
|
||||
$response->headers->remove('X-Body-Eval');
|
||||
$response->headers->remove('X-Body-File');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($response->headers->has('X-Body-Eval')) {
|
||||
ob_start();
|
||||
|
||||
|
@ -656,7 +648,11 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
|||
$response->headers->set('Content-Length', strlen($response->getContent()));
|
||||
}
|
||||
} elseif ($response->headers->has('X-Body-File')) {
|
||||
$response->setContent(file_get_contents($response->headers->get('X-Body-File')));
|
||||
// Response does not include possibly dynamic content (ESI, SSI), so we need
|
||||
// not handle the content for HEAD requests
|
||||
if (!$request->isMethod('HEAD')) {
|
||||
$response->setContent(file_get_contents($response->headers->get('X-Body-File')));
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1133,7 +1133,7 @@ class HttpCacheTest extends HttpCacheTestCase
|
|||
array(
|
||||
'status' => 200,
|
||||
'body' => 'Hello World!',
|
||||
'headers' => array('Cache-Control' => 's-maxage=300'),
|
||||
'headers' => array('Cache-Control' => 's-maxage=200'),
|
||||
),
|
||||
array(
|
||||
'status' => 200,
|
||||
|
@ -1147,8 +1147,33 @@ class HttpCacheTest extends HttpCacheTestCase
|
|||
$this->request('GET', '/', array(), array(), true);
|
||||
$this->assertEquals('Hello World! My name is Bobby.', $this->response->getContent());
|
||||
|
||||
// check for 100 or 99 as the test can be executed after a second change
|
||||
$this->assertTrue(in_array($this->response->getTtl(), array(99, 100)));
|
||||
$this->assertEquals(100, $this->response->getTtl());
|
||||
}
|
||||
|
||||
public function testEsiCacheSendsTheLowestTtlForHeadRequests()
|
||||
{
|
||||
$responses = array(
|
||||
array(
|
||||
'status' => 200,
|
||||
'body' => 'I am a long-lived master response, but I embed a short-lived resource: <esi:include src="/foo" />',
|
||||
'headers' => array(
|
||||
'Cache-Control' => 's-maxage=300',
|
||||
'Surrogate-Control' => 'content="ESI/1.0"',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'status' => 200,
|
||||
'body' => 'I am a short-lived resource',
|
||||
'headers' => array('Cache-Control' => 's-maxage=100'),
|
||||
),
|
||||
);
|
||||
|
||||
$this->setNextResponses($responses);
|
||||
|
||||
$this->request('HEAD', '/', array(), array(), true);
|
||||
|
||||
$this->assertEmpty($this->response->getContent());
|
||||
$this->assertEquals(100, $this->response->getTtl());
|
||||
}
|
||||
|
||||
public function testEsiCacheForceValidation()
|
||||
|
@ -1184,6 +1209,37 @@ class HttpCacheTest extends HttpCacheTestCase
|
|||
$this->assertTrue($this->response->headers->hasCacheControlDirective('no-cache'));
|
||||
}
|
||||
|
||||
public function testEsiCacheForceValidationForHeadRequests()
|
||||
{
|
||||
$responses = array(
|
||||
array(
|
||||
'status' => 200,
|
||||
'body' => 'I am the master response and use expiration caching, but I embed another resource: <esi:include src="/foo" />',
|
||||
'headers' => array(
|
||||
'Cache-Control' => 's-maxage=300',
|
||||
'Surrogate-Control' => 'content="ESI/1.0"',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'status' => 200,
|
||||
'body' => 'I am the embedded resource and use validation caching',
|
||||
'headers' => array('ETag' => 'foobar'),
|
||||
),
|
||||
);
|
||||
|
||||
$this->setNextResponses($responses);
|
||||
|
||||
$this->request('HEAD', '/', array(), array(), true);
|
||||
|
||||
// The response has been assembled from expiration and validation based resources
|
||||
// This can neither be cached nor revalidated, so it should be private/no cache
|
||||
$this->assertEmpty($this->response->getContent());
|
||||
$this->assertNull($this->response->getTtl());
|
||||
$this->assertTrue($this->response->mustRevalidate());
|
||||
$this->assertTrue($this->response->headers->hasCacheControlDirective('private'));
|
||||
$this->assertTrue($this->response->headers->hasCacheControlDirective('no-cache'));
|
||||
}
|
||||
|
||||
public function testEsiRecalculateContentLengthHeader()
|
||||
{
|
||||
$responses = array(
|
||||
|
@ -1192,7 +1248,6 @@ class HttpCacheTest extends HttpCacheTestCase
|
|||
'body' => '<esi:include src="/foo" />',
|
||||
'headers' => array(
|
||||
'Content-Length' => 26,
|
||||
'Cache-Control' => 's-maxage=300',
|
||||
'Surrogate-Control' => 'content="ESI/1.0"',
|
||||
),
|
||||
),
|
||||
|
@ -1210,6 +1265,37 @@ class HttpCacheTest extends HttpCacheTestCase
|
|||
$this->assertEquals(12, $this->response->headers->get('Content-Length'));
|
||||
}
|
||||
|
||||
public function testEsiRecalculateContentLengthHeaderForHeadRequest()
|
||||
{
|
||||
$responses = array(
|
||||
array(
|
||||
'status' => 200,
|
||||
'body' => '<esi:include src="/foo" />',
|
||||
'headers' => array(
|
||||
'Content-Length' => 26,
|
||||
'Surrogate-Control' => 'content="ESI/1.0"',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'status' => 200,
|
||||
'body' => 'Hello World!',
|
||||
'headers' => array(),
|
||||
),
|
||||
);
|
||||
|
||||
$this->setNextResponses($responses);
|
||||
|
||||
$this->request('HEAD', '/', array(), array(), true);
|
||||
|
||||
// https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13
|
||||
// "The Content-Length entity-header field indicates the size of the entity-body,
|
||||
// in decimal number of OCTETs, sent to the recipient or, in the case of the HEAD
|
||||
// method, the size of the entity-body that would have been sent had the request
|
||||
// been a GET."
|
||||
$this->assertEmpty($this->response->getContent());
|
||||
$this->assertEquals(12, $this->response->headers->get('Content-Length'));
|
||||
}
|
||||
|
||||
public function testClientIpIsAlwaysLocalhostForForwardedRequests()
|
||||
{
|
||||
$this->setNextResponse();
|
||||
|
@ -1301,6 +1387,35 @@ class HttpCacheTest extends HttpCacheTestCase
|
|||
$this->assertNull($this->response->getLastModified());
|
||||
}
|
||||
|
||||
public function testEsiCacheRemoveValidationHeadersIfEmbeddedResponsesAndHeadRequest()
|
||||
{
|
||||
$time = \DateTime::createFromFormat('U', time());
|
||||
|
||||
$responses = array(
|
||||
array(
|
||||
'status' => 200,
|
||||
'body' => '<esi:include src="/hey" />',
|
||||
'headers' => array(
|
||||
'Surrogate-Control' => 'content="ESI/1.0"',
|
||||
'ETag' => 'hey',
|
||||
'Last-Modified' => $time->format(DATE_RFC2822),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'status' => 200,
|
||||
'body' => 'Hey!',
|
||||
'headers' => array(),
|
||||
),
|
||||
);
|
||||
|
||||
$this->setNextResponses($responses);
|
||||
|
||||
$this->request('HEAD', '/', array(), array(), true);
|
||||
$this->assertEmpty($this->response->getContent());
|
||||
$this->assertNull($this->response->getETag());
|
||||
$this->assertNull($this->response->getLastModified());
|
||||
}
|
||||
|
||||
public function testDoesNotCacheOptionsRequest()
|
||||
{
|
||||
$this->setNextResponse(200, array('Cache-Control' => 'public, s-maxage=60'), 'get');
|
||||
|
|
Reference in New Issue