Aggiornato Composer
This commit is contained in:
@@ -95,7 +95,7 @@ abstract class AbstractSurrogate implements SurrogateInterface
|
||||
try {
|
||||
$response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true);
|
||||
|
||||
if (!$response->isSuccessful()) {
|
||||
if (!$response->isSuccessful() && Response::HTTP_NOT_MODIFIED !== $response->getStatusCode()) {
|
||||
throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %d).', $subRequest->getUri(), $response->getStatusCode()));
|
||||
}
|
||||
|
||||
@@ -133,4 +133,15 @@ abstract class AbstractSurrogate implements SurrogateInterface
|
||||
$response->headers->set('Surrogate-Control', preg_replace(sprintf('#content="%s/1.0",\s*#', $upperName), '', $value));
|
||||
}
|
||||
}
|
||||
|
||||
protected static function generateBodyEvalBoundary(): string
|
||||
{
|
||||
static $cookie;
|
||||
$cookie = hash('md5', $cookie ?? $cookie = random_bytes(16), true);
|
||||
$boundary = base64_encode($cookie);
|
||||
|
||||
\assert(HttpCache::BODY_EVAL_BOUNDARY_LENGTH === \strlen($boundary));
|
||||
|
||||
return $boundary;
|
||||
}
|
||||
}
|
||||
|
||||
16
vendor/symfony/http-kernel/HttpCache/Esi.php
vendored
16
vendor/symfony/http-kernel/HttpCache/Esi.php
vendored
@@ -45,7 +45,7 @@ class Esi extends AbstractSurrogate
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = '')
|
||||
public function renderIncludeTag(string $uri, ?string $alt = null, bool $ignoreErrors = true, string $comment = '')
|
||||
{
|
||||
$html = sprintf('<esi:include src="%s"%s%s />',
|
||||
$uri,
|
||||
@@ -80,8 +80,8 @@ class Esi extends AbstractSurrogate
|
||||
$content = preg_replace('#<esi\:remove>.*?</esi\:remove>#s', '', $content);
|
||||
$content = preg_replace('#<esi\:comment[^>]+>#s', '', $content);
|
||||
|
||||
$boundary = self::generateBodyEvalBoundary();
|
||||
$chunks = preg_split('#<esi\:include\s+(.*?)\s*(?:/|</esi\:include)>#', $content, -1, \PREG_SPLIT_DELIM_CAPTURE);
|
||||
$chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]);
|
||||
|
||||
$i = 1;
|
||||
while (isset($chunks[$i])) {
|
||||
@@ -95,16 +95,10 @@ class Esi extends AbstractSurrogate
|
||||
throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.');
|
||||
}
|
||||
|
||||
$chunks[$i] = sprintf('<?php echo $this->surrogate->handle($this, %s, %s, %s) ?>'."\n",
|
||||
var_export($options['src'], true),
|
||||
var_export($options['alt'] ?? '', true),
|
||||
isset($options['onerror']) && 'continue' === $options['onerror'] ? 'true' : 'false'
|
||||
);
|
||||
++$i;
|
||||
$chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]);
|
||||
++$i;
|
||||
$chunks[$i] = $boundary.$options['src']."\n".($options['alt'] ?? '')."\n".('continue' === ($options['onerror'] ?? ''))."\n";
|
||||
$i += 2;
|
||||
}
|
||||
$content = implode('', $chunks);
|
||||
$content = $boundary.implode('', $chunks).$boundary;
|
||||
|
||||
$response->setContent($content);
|
||||
$response->headers->set('X-Body-Eval', 'ESI');
|
||||
|
||||
@@ -29,6 +29,8 @@ use Symfony\Component\HttpKernel\TerminableInterface;
|
||||
*/
|
||||
class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
{
|
||||
public const BODY_EVAL_BOUNDARY_LENGTH = 24;
|
||||
|
||||
private $kernel;
|
||||
private $store;
|
||||
private $request;
|
||||
@@ -79,7 +81,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
* This setting is overridden by the stale-if-error HTTP Cache-Control extension
|
||||
* (see RFC 5861).
|
||||
*/
|
||||
public function __construct(HttpKernelInterface $kernel, StoreInterface $store, SurrogateInterface $surrogate = null, array $options = [])
|
||||
public function __construct(HttpKernelInterface $kernel, StoreInterface $store, ?SurrogateInterface $surrogate = null, array $options = [])
|
||||
{
|
||||
$this->store = $store;
|
||||
$this->kernel = $kernel;
|
||||
@@ -469,7 +471,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
protected function forward(Request $request, bool $catch = false, Response $entry = null)
|
||||
protected function forward(Request $request, bool $catch = false, ?Response $entry = null)
|
||||
{
|
||||
if ($this->surrogate) {
|
||||
$this->surrogate->addSurrogateCapability($request);
|
||||
@@ -631,12 +633,22 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
private function restoreResponseBody(Request $request, Response $response)
|
||||
{
|
||||
if ($response->headers->has('X-Body-Eval')) {
|
||||
\assert(self::BODY_EVAL_BOUNDARY_LENGTH === 24);
|
||||
|
||||
ob_start();
|
||||
|
||||
if ($response->headers->has('X-Body-File')) {
|
||||
include $response->headers->get('X-Body-File');
|
||||
} else {
|
||||
eval('; ?>'.$response->getContent().'<?php ;');
|
||||
$content = $response->getContent();
|
||||
$boundary = substr($content, 0, 24);
|
||||
$j = strpos($content, $boundary, 24);
|
||||
echo substr($content, 24, $j - 24);
|
||||
$i = $j + 24;
|
||||
|
||||
while (false !== $j = strpos($content, $boundary, $i)) {
|
||||
[$uri, $alt, $ignoreErrors, $part] = explode("\n", substr($content, $i, $j - $i), 4);
|
||||
$i = $j + 24;
|
||||
|
||||
echo $this->surrogate->handle($this, $uri, $alt, $ignoreErrors);
|
||||
echo $part;
|
||||
}
|
||||
|
||||
$response->setContent(ob_get_clean());
|
||||
@@ -718,7 +730,11 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
$timeout = $this->options['stale_while_revalidate'];
|
||||
}
|
||||
|
||||
return abs($entry->getTtl()) < $timeout;
|
||||
$age = $entry->getAge();
|
||||
$maxAge = $entry->getMaxAge() ?? 0;
|
||||
$ttl = $maxAge - $age;
|
||||
|
||||
return abs($ttl) < $timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -147,7 +147,7 @@ class ResponseCacheStrategy implements ResponseCacheStrategyInterface
|
||||
|
||||
if (is_numeric($this->ageDirectives['expires'])) {
|
||||
$date = clone $response->getDate();
|
||||
$date->modify('+'.($this->ageDirectives['expires'] + $this->age).' seconds');
|
||||
$date = $date->modify('+'.($this->ageDirectives['expires'] + $this->age).' seconds');
|
||||
$response->setExpires($date);
|
||||
}
|
||||
}
|
||||
|
||||
15
vendor/symfony/http-kernel/HttpCache/Ssi.php
vendored
15
vendor/symfony/http-kernel/HttpCache/Ssi.php
vendored
@@ -42,7 +42,7 @@ class Ssi extends AbstractSurrogate
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = '')
|
||||
public function renderIncludeTag(string $uri, ?string $alt = null, bool $ignoreErrors = true, string $comment = '')
|
||||
{
|
||||
return sprintf('<!--#include virtual="%s" -->', $uri);
|
||||
}
|
||||
@@ -64,9 +64,8 @@ class Ssi extends AbstractSurrogate
|
||||
|
||||
// we don't use a proper XML parser here as we can have SSI tags in a plain text response
|
||||
$content = $response->getContent();
|
||||
|
||||
$boundary = self::generateBodyEvalBoundary();
|
||||
$chunks = preg_split('#<!--\#include\s+(.*?)\s*-->#', $content, -1, \PREG_SPLIT_DELIM_CAPTURE);
|
||||
$chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]);
|
||||
|
||||
$i = 1;
|
||||
while (isset($chunks[$i])) {
|
||||
@@ -80,14 +79,10 @@ class Ssi extends AbstractSurrogate
|
||||
throw new \RuntimeException('Unable to process an SSI tag without a "virtual" attribute.');
|
||||
}
|
||||
|
||||
$chunks[$i] = sprintf('<?php echo $this->surrogate->handle($this, %s, \'\', false) ?>'."\n",
|
||||
var_export($options['virtual'], true)
|
||||
);
|
||||
++$i;
|
||||
$chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]);
|
||||
++$i;
|
||||
$chunks[$i] = $boundary.$options['virtual']."\n\n\n";
|
||||
$i += 2;
|
||||
}
|
||||
$content = implode('', $chunks);
|
||||
$content = $boundary.implode('', $chunks).$boundary;
|
||||
|
||||
$response->setContent($content);
|
||||
$response->headers->set('X-Body-Eval', 'SSI');
|
||||
|
||||
33
vendor/symfony/http-kernel/HttpCache/Store.php
vendored
33
vendor/symfony/http-kernel/HttpCache/Store.php
vendored
@@ -29,17 +29,28 @@ class Store implements StoreInterface
|
||||
private $keyCache;
|
||||
/** @var array<string, resource> */
|
||||
private $locks = [];
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* The available options are:
|
||||
*
|
||||
* * private_headers Set of response headers that should not be stored
|
||||
* when a response is cached. (default: Set-Cookie)
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function __construct(string $root)
|
||||
public function __construct(string $root, array $options = [])
|
||||
{
|
||||
$this->root = $root;
|
||||
if (!is_dir($this->root) && !@mkdir($this->root, 0777, true) && !is_dir($this->root)) {
|
||||
throw new \RuntimeException(sprintf('Unable to create the store directory (%s).', $this->root));
|
||||
}
|
||||
$this->keyCache = new \SplObjectStorage();
|
||||
$this->options = array_merge([
|
||||
'private_headers' => ['Set-Cookie'],
|
||||
], $options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,7 +197,7 @@ class Store implements StoreInterface
|
||||
if ($this->getPath($digest) !== $response->headers->get('X-Body-File')) {
|
||||
throw new \RuntimeException('X-Body-File and X-Content-Digest do not match.');
|
||||
}
|
||||
// Everything seems ok, omit writing content to disk
|
||||
// Everything seems ok, omit writing content to disk
|
||||
} else {
|
||||
$digest = $this->generateContentDigest($response);
|
||||
$response->headers->set('X-Content-Digest', $digest);
|
||||
@@ -216,6 +227,10 @@ class Store implements StoreInterface
|
||||
$headers = $this->persistResponse($response);
|
||||
unset($headers['age']);
|
||||
|
||||
foreach ($this->options['private_headers'] as $h) {
|
||||
unset($headers[strtolower($h)]);
|
||||
}
|
||||
|
||||
array_unshift($entries, [$storedEnv, $headers]);
|
||||
|
||||
if (!$this->save($key, serialize($entries))) {
|
||||
@@ -460,15 +475,25 @@ class Store implements StoreInterface
|
||||
/**
|
||||
* Restores a Response from the HTTP headers and body.
|
||||
*/
|
||||
private function restoreResponse(array $headers, string $path = null): Response
|
||||
private function restoreResponse(array $headers, ?string $path = null): ?Response
|
||||
{
|
||||
$status = $headers['X-Status'][0];
|
||||
unset($headers['X-Status']);
|
||||
$content = null;
|
||||
|
||||
if (null !== $path) {
|
||||
$headers['X-Body-File'] = [$path];
|
||||
unset($headers['x-body-file']);
|
||||
|
||||
if ($headers['X-Body-Eval'] ?? $headers['x-body-eval'] ?? false) {
|
||||
$content = file_get_contents($path);
|
||||
\assert(HttpCache::BODY_EVAL_BOUNDARY_LENGTH === 24);
|
||||
if (48 > \strlen($content) || substr($content, -24) !== substr($content, 0, 24)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Response($path, $status, $headers);
|
||||
return new Response($content, $status, $headers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,12 +59,12 @@ interface SurrogateInterface
|
||||
/**
|
||||
* Renders a Surrogate tag.
|
||||
*
|
||||
* @param string $alt An alternate URI
|
||||
* @param string $comment A comment to add as an esi:include tag
|
||||
* @param string|null $alt An alternate URI
|
||||
* @param string $comment A comment to add as an esi:include tag
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = '');
|
||||
public function renderIncludeTag(string $uri, ?string $alt = null, bool $ignoreErrors = true, string $comment = '');
|
||||
|
||||
/**
|
||||
* Replaces a Response Surrogate tags with the included resource content.
|
||||
|
||||
Reference in New Issue
Block a user