| 148 |
lars |
1 |
<?php
|
|
|
2 |
|
|
|
3 |
/*
|
|
|
4 |
* This file is part of the Symfony package.
|
|
|
5 |
*
|
|
|
6 |
* (c) Fabien Potencier <fabien@symfony.com>
|
|
|
7 |
*
|
|
|
8 |
* For the full copyright and license information, please view the LICENSE
|
|
|
9 |
* file that was distributed with this source code.
|
|
|
10 |
*/
|
|
|
11 |
|
|
|
12 |
namespace Symfony\Component\HttpKernel\HttpCache;
|
|
|
13 |
|
|
|
14 |
use Symfony\Component\HttpFoundation\Request;
|
|
|
15 |
use Symfony\Component\HttpFoundation\Response;
|
|
|
16 |
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
|
|
17 |
|
|
|
18 |
/**
|
|
|
19 |
* Abstract class implementing Surrogate capabilities to Request and Response instances.
|
|
|
20 |
*
|
|
|
21 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
22 |
* @author Robin Chalas <robin.chalas@gmail.com>
|
|
|
23 |
*/
|
|
|
24 |
abstract class AbstractSurrogate implements SurrogateInterface
|
|
|
25 |
{
|
|
|
26 |
protected $contentTypes;
|
|
|
27 |
protected $phpEscapeMap = [
|
|
|
28 |
['<?', '<%', '<s', '<S'],
|
|
|
29 |
['<?php echo "<?"; ?>', '<?php echo "<%"; ?>', '<?php echo "<s"; ?>', '<?php echo "<S"; ?>'],
|
|
|
30 |
];
|
|
|
31 |
|
|
|
32 |
/**
|
|
|
33 |
* @param array $contentTypes An array of content-type that should be parsed for Surrogate information
|
|
|
34 |
* (default: text/html, text/xml, application/xhtml+xml, and application/xml)
|
|
|
35 |
*/
|
|
|
36 |
public function __construct(array $contentTypes = ['text/html', 'text/xml', 'application/xhtml+xml', 'application/xml'])
|
|
|
37 |
{
|
|
|
38 |
$this->contentTypes = $contentTypes;
|
|
|
39 |
}
|
|
|
40 |
|
|
|
41 |
/**
|
|
|
42 |
* Returns a new cache strategy instance.
|
|
|
43 |
*/
|
|
|
44 |
public function createCacheStrategy(): ResponseCacheStrategyInterface
|
|
|
45 |
{
|
|
|
46 |
return new ResponseCacheStrategy();
|
|
|
47 |
}
|
|
|
48 |
|
|
|
49 |
public function hasSurrogateCapability(Request $request): bool
|
|
|
50 |
{
|
|
|
51 |
if (null === $value = $request->headers->get('Surrogate-Capability')) {
|
|
|
52 |
return false;
|
|
|
53 |
}
|
|
|
54 |
|
|
|
55 |
return str_contains($value, sprintf('%s/1.0', strtoupper($this->getName())));
|
|
|
56 |
}
|
|
|
57 |
|
|
|
58 |
public function addSurrogateCapability(Request $request)
|
|
|
59 |
{
|
|
|
60 |
$current = $request->headers->get('Surrogate-Capability');
|
|
|
61 |
$new = sprintf('symfony="%s/1.0"', strtoupper($this->getName()));
|
|
|
62 |
|
|
|
63 |
$request->headers->set('Surrogate-Capability', $current ? $current.', '.$new : $new);
|
|
|
64 |
}
|
|
|
65 |
|
|
|
66 |
public function needsParsing(Response $response): bool
|
|
|
67 |
{
|
|
|
68 |
if (!$control = $response->headers->get('Surrogate-Control')) {
|
|
|
69 |
return false;
|
|
|
70 |
}
|
|
|
71 |
|
|
|
72 |
$pattern = sprintf('#content="[^"]*%s/1.0[^"]*"#', strtoupper($this->getName()));
|
|
|
73 |
|
|
|
74 |
return (bool) preg_match($pattern, $control);
|
|
|
75 |
}
|
|
|
76 |
|
|
|
77 |
public function handle(HttpCache $cache, string $uri, string $alt, bool $ignoreErrors): string
|
|
|
78 |
{
|
|
|
79 |
$subRequest = Request::create($uri, Request::METHOD_GET, [], $cache->getRequest()->cookies->all(), [], $cache->getRequest()->server->all());
|
|
|
80 |
|
|
|
81 |
try {
|
|
|
82 |
$response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true);
|
|
|
83 |
|
|
|
84 |
if (!$response->isSuccessful() && Response::HTTP_NOT_MODIFIED !== $response->getStatusCode()) {
|
|
|
85 |
throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %d).', $subRequest->getUri(), $response->getStatusCode()));
|
|
|
86 |
}
|
|
|
87 |
|
|
|
88 |
return $response->getContent();
|
|
|
89 |
} catch (\Exception $e) {
|
|
|
90 |
if ($alt) {
|
|
|
91 |
return $this->handle($cache, $alt, '', $ignoreErrors);
|
|
|
92 |
}
|
|
|
93 |
|
|
|
94 |
if (!$ignoreErrors) {
|
|
|
95 |
throw $e;
|
|
|
96 |
}
|
|
|
97 |
}
|
|
|
98 |
|
|
|
99 |
return '';
|
|
|
100 |
}
|
|
|
101 |
|
|
|
102 |
/**
|
|
|
103 |
* Remove the Surrogate from the Surrogate-Control header.
|
|
|
104 |
*/
|
|
|
105 |
protected function removeFromControl(Response $response)
|
|
|
106 |
{
|
|
|
107 |
if (!$response->headers->has('Surrogate-Control')) {
|
|
|
108 |
return;
|
|
|
109 |
}
|
|
|
110 |
|
|
|
111 |
$value = $response->headers->get('Surrogate-Control');
|
|
|
112 |
$upperName = strtoupper($this->getName());
|
|
|
113 |
|
|
|
114 |
if (sprintf('content="%s/1.0"', $upperName) == $value) {
|
|
|
115 |
$response->headers->remove('Surrogate-Control');
|
|
|
116 |
} elseif (preg_match(sprintf('#,\s*content="%s/1.0"#', $upperName), $value)) {
|
|
|
117 |
$response->headers->set('Surrogate-Control', preg_replace(sprintf('#,\s*content="%s/1.0"#', $upperName), '', $value));
|
|
|
118 |
} elseif (preg_match(sprintf('#content="%s/1.0",\s*#', $upperName), $value)) {
|
|
|
119 |
$response->headers->set('Surrogate-Control', preg_replace(sprintf('#content="%s/1.0",\s*#', $upperName), '', $value));
|
|
|
120 |
}
|
|
|
121 |
}
|
|
|
122 |
}
|