Merge branch '2.1' into 2.2
* 2.1: remove validation related headers when needed use while loop for iterating [Filesystem] copy() is not working when open_basedir is set Conflicts: src/Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php
This commit is contained in:
commit
9f02b05997
@ -35,6 +35,10 @@ class Filesystem
|
|||||||
*/
|
*/
|
||||||
public function copy($originFile, $targetFile, $override = false)
|
public function copy($originFile, $targetFile, $override = false)
|
||||||
{
|
{
|
||||||
|
if (!is_file($originFile)) {
|
||||||
|
throw new IOException(sprintf('Failed to copy %s because file not exists', $originFile));
|
||||||
|
}
|
||||||
|
|
||||||
$this->mkdir(dirname($targetFile));
|
$this->mkdir(dirname($targetFile));
|
||||||
|
|
||||||
if (!$override && is_file($targetFile)) {
|
if (!$override && is_file($targetFile)) {
|
||||||
@ -44,7 +48,15 @@ class Filesystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($doCopy) {
|
if ($doCopy) {
|
||||||
if (true !== @copy($originFile, $targetFile)) {
|
// https://bugs.php.net/bug.php?id=64634
|
||||||
|
$source = fopen($originFile, 'r');
|
||||||
|
$target = fopen($targetFile, 'w+');
|
||||||
|
stream_copy_to_stream($source, $target);
|
||||||
|
fclose($source);
|
||||||
|
fclose($target);
|
||||||
|
unset($source, $target);
|
||||||
|
|
||||||
|
if (!is_file($targetFile)) {
|
||||||
throw new IOException(sprintf('Failed to copy %s to %s', $originFile, $targetFile));
|
throw new IOException(sprintf('Failed to copy %s to %s', $originFile, $targetFile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,13 +29,12 @@ use Symfony\Component\HttpFoundation\Response;
|
|||||||
class EsiResponseCacheStrategy implements EsiResponseCacheStrategyInterface
|
class EsiResponseCacheStrategy implements EsiResponseCacheStrategyInterface
|
||||||
{
|
{
|
||||||
private $cacheable = true;
|
private $cacheable = true;
|
||||||
|
private $embeddedResponses = 0;
|
||||||
private $ttls = array();
|
private $ttls = array();
|
||||||
private $maxAges = array();
|
private $maxAges = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a Response.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param Response $response
|
|
||||||
*/
|
*/
|
||||||
public function add(Response $response)
|
public function add(Response $response)
|
||||||
{
|
{
|
||||||
@ -45,26 +44,38 @@ class EsiResponseCacheStrategy implements EsiResponseCacheStrategyInterface
|
|||||||
$this->ttls[] = $response->getTtl();
|
$this->ttls[] = $response->getTtl();
|
||||||
$this->maxAges[] = $response->getMaxAge();
|
$this->maxAges[] = $response->getMaxAge();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->embeddedResponses++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the Response HTTP headers based on the embedded Responses.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param Response $response
|
|
||||||
*/
|
*/
|
||||||
public function update(Response $response)
|
public function update(Response $response)
|
||||||
{
|
{
|
||||||
// if we only have one Response, do nothing
|
// if we have no embedded Response, do nothing
|
||||||
if (1 === count($this->ttls)) {
|
if (0 === $this->embeddedResponses) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove validation related headers in order to avoid browsers using
|
||||||
|
// their own cache, because some of the response content comes from
|
||||||
|
// at least one embedded response (which likely has a different caching strategy).
|
||||||
|
if ($response->isValidateable()) {
|
||||||
|
$response->setEtag(null);
|
||||||
|
$response->setLastModified(null);
|
||||||
|
$this->cacheable = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!$this->cacheable) {
|
if (!$this->cacheable) {
|
||||||
$response->headers->set('Cache-Control', 'no-cache, must-revalidate');
|
$response->headers->set('Cache-Control', 'no-cache, must-revalidate');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->ttls[] = $response->getTtl();
|
||||||
|
$this->maxAges[] = $response->getMaxAge();
|
||||||
|
|
||||||
if (null !== $maxAge = min($this->maxAges)) {
|
if (null !== $maxAge = min($this->maxAges)) {
|
||||||
$response->setSharedMaxAge($maxAge);
|
$response->setSharedMaxAge($maxAge);
|
||||||
$response->headers->set('Age', $maxAge - min($this->ttls));
|
$response->headers->set('Age', $maxAge - min($this->ttls));
|
||||||
|
@ -205,10 +205,10 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (null !== $this->esi) {
|
if (null !== $this->esi) {
|
||||||
$this->esiCacheStrategy->add($response);
|
|
||||||
|
|
||||||
if (HttpKernelInterface::MASTER_REQUEST === $type) {
|
if (HttpKernelInterface::MASTER_REQUEST === $type) {
|
||||||
$this->esiCacheStrategy->update($response);
|
$this->esiCacheStrategy->update($response);
|
||||||
|
} else {
|
||||||
|
$this->esiCacheStrategy->add($response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,14 +60,7 @@ class FileProfilerStorage implements ProfilerStorageInterface
|
|||||||
fseek($file, 0, SEEK_END);
|
fseek($file, 0, SEEK_END);
|
||||||
|
|
||||||
$result = array();
|
$result = array();
|
||||||
|
while (count($result) < $limit && $line = $this->readLineFromFile($file)) {
|
||||||
for (;$limit > 0; $limit--) {
|
|
||||||
$line = $this->readLineFromFile($file);
|
|
||||||
|
|
||||||
if (null === $line) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent) = str_getcsv($line);
|
list($csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent) = str_getcsv($line);
|
||||||
|
|
||||||
$csvTime = (int) $csvTime;
|
$csvTime = (int) $csvTime;
|
||||||
|
@ -1075,4 +1075,32 @@ class HttpCacheTest extends HttpCacheTestCase
|
|||||||
|
|
||||||
$this->assertEquals('10.0.0.1', $this->kernel->getBackendRequest()->headers->get('X-Forwarded-For'));
|
$this->assertEquals('10.0.0.1', $this->kernel->getBackendRequest()->headers->get('X-Forwarded-For'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testEsiCacheRemoveValidationHeadersIfEmbeddedResponses()
|
||||||
|
{
|
||||||
|
$time = new \DateTime;
|
||||||
|
|
||||||
|
$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('GET', '/', array(), array(), true);
|
||||||
|
$this->assertNull($this->response->getETag());
|
||||||
|
$this->assertNull($this->response->getLastModified());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,6 +189,21 @@ abstract class AbstractProfilerStorageTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->getStorage()->purge();
|
$this->getStorage()->purge();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testRetrieveByMethodAndLimit()
|
||||||
|
{
|
||||||
|
foreach (array('POST', 'GET') as $method) {
|
||||||
|
for ($i = 0; $i < 5; $i++) {
|
||||||
|
$profile = new Profile('token_'.$i.$method);
|
||||||
|
$profile->setMethod($method);
|
||||||
|
$this->getStorage()->write($profile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertCount(5, $this->getStorage()->find('', '', 5, 'POST'));
|
||||||
|
|
||||||
|
$this->getStorage()->purge();
|
||||||
|
}
|
||||||
|
|
||||||
public function testPurge()
|
public function testPurge()
|
||||||
{
|
{
|
||||||
$profile = new Profile('token1');
|
$profile = new Profile('token1');
|
||||||
|
Reference in New Issue
Block a user