Mercurial > hg > isophonics-drupal-site
comparison vendor/symfony/http-kernel/HttpCache/HttpCache.php @ 17:129ea1e6d783
Update, including to Drupal core 8.6.10
author | Chris Cannam |
---|---|
date | Thu, 28 Feb 2019 13:21:36 +0000 |
parents | c2387f117808 |
children |
comparison
equal
deleted
inserted
replaced
16:c2387f117808 | 17:129ea1e6d783 |
---|---|
13 * file that was distributed with this source code. | 13 * file that was distributed with this source code. |
14 */ | 14 */ |
15 | 15 |
16 namespace Symfony\Component\HttpKernel\HttpCache; | 16 namespace Symfony\Component\HttpKernel\HttpCache; |
17 | 17 |
18 use Symfony\Component\HttpFoundation\Request; | |
19 use Symfony\Component\HttpFoundation\Response; | |
18 use Symfony\Component\HttpKernel\HttpKernelInterface; | 20 use Symfony\Component\HttpKernel\HttpKernelInterface; |
19 use Symfony\Component\HttpKernel\TerminableInterface; | 21 use Symfony\Component\HttpKernel\TerminableInterface; |
20 use Symfony\Component\HttpFoundation\Request; | |
21 use Symfony\Component\HttpFoundation\Response; | |
22 | 22 |
23 /** | 23 /** |
24 * Cache provides HTTP caching. | 24 * Cache provides HTTP caching. |
25 * | 25 * |
26 * @author Fabien Potencier <fabien@symfony.com> | 26 * @author Fabien Potencier <fabien@symfony.com> |
30 private $kernel; | 30 private $kernel; |
31 private $store; | 31 private $store; |
32 private $request; | 32 private $request; |
33 private $surrogate; | 33 private $surrogate; |
34 private $surrogateCacheStrategy; | 34 private $surrogateCacheStrategy; |
35 private $options = array(); | 35 private $options = []; |
36 private $traces = array(); | 36 private $traces = []; |
37 | 37 |
38 /** | 38 /** |
39 * Constructor. | 39 * Constructor. |
40 * | 40 * |
41 * The available options are: | 41 * The available options are: |
68 * * stale_if_error Specifies the default number of seconds (the granularity is the second) during which | 68 * * stale_if_error Specifies the default number of seconds (the granularity is the second) during which |
69 * the cache can serve a stale response when an error is encountered (default: 60). | 69 * the cache can serve a stale response when an error is encountered (default: 60). |
70 * This setting is overridden by the stale-if-error HTTP Cache-Control extension | 70 * This setting is overridden by the stale-if-error HTTP Cache-Control extension |
71 * (see RFC 5861). | 71 * (see RFC 5861). |
72 */ | 72 */ |
73 public function __construct(HttpKernelInterface $kernel, StoreInterface $store, SurrogateInterface $surrogate = null, array $options = array()) | 73 public function __construct(HttpKernelInterface $kernel, StoreInterface $store, SurrogateInterface $surrogate = null, array $options = []) |
74 { | 74 { |
75 $this->store = $store; | 75 $this->store = $store; |
76 $this->kernel = $kernel; | 76 $this->kernel = $kernel; |
77 $this->surrogate = $surrogate; | 77 $this->surrogate = $surrogate; |
78 | 78 |
79 // needed in case there is a fatal error because the backend is too slow to respond | 79 // needed in case there is a fatal error because the backend is too slow to respond |
80 register_shutdown_function(array($this->store, 'cleanup')); | 80 register_shutdown_function([$this->store, 'cleanup']); |
81 | 81 |
82 $this->options = array_merge(array( | 82 $this->options = array_merge([ |
83 'debug' => false, | 83 'debug' => false, |
84 'default_ttl' => 0, | 84 'default_ttl' => 0, |
85 'private_headers' => array('Authorization', 'Cookie'), | 85 'private_headers' => ['Authorization', 'Cookie'], |
86 'allow_reload' => false, | 86 'allow_reload' => false, |
87 'allow_revalidate' => false, | 87 'allow_revalidate' => false, |
88 'stale_while_revalidate' => 2, | 88 'stale_while_revalidate' => 2, |
89 'stale_if_error' => 60, | 89 'stale_if_error' => 60, |
90 ), $options); | 90 ], $options); |
91 } | 91 } |
92 | 92 |
93 /** | 93 /** |
94 * Gets the current store. | 94 * Gets the current store. |
95 * | 95 * |
96 * @return StoreInterface $store A StoreInterface instance | 96 * @return StoreInterface A StoreInterface instance |
97 */ | 97 */ |
98 public function getStore() | 98 public function getStore() |
99 { | 99 { |
100 return $this->store; | 100 return $this->store; |
101 } | 101 } |
115 * | 115 * |
116 * @return string A log message | 116 * @return string A log message |
117 */ | 117 */ |
118 public function getLog() | 118 public function getLog() |
119 { | 119 { |
120 $log = array(); | 120 $log = []; |
121 foreach ($this->traces as $request => $traces) { | 121 foreach ($this->traces as $request => $traces) { |
122 $log[] = sprintf('%s: %s', $request, implode(', ', $traces)); | 122 $log[] = sprintf('%s: %s', $request, implode(', ', $traces)); |
123 } | 123 } |
124 | 124 |
125 return implode('; ', $log); | 125 return implode('; ', $log); |
162 */ | 162 */ |
163 public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) | 163 public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) |
164 { | 164 { |
165 // FIXME: catch exceptions and implement a 500 error page here? -> in Varnish, there is a built-in error page mechanism | 165 // FIXME: catch exceptions and implement a 500 error page here? -> in Varnish, there is a built-in error page mechanism |
166 if (HttpKernelInterface::MASTER_REQUEST === $type) { | 166 if (HttpKernelInterface::MASTER_REQUEST === $type) { |
167 $this->traces = array(); | 167 $this->traces = []; |
168 // Keep a clone of the original request for surrogates so they can access it. | 168 // Keep a clone of the original request for surrogates so they can access it. |
169 // We must clone here to get a separate instance because the application will modify the request during | 169 // We must clone here to get a separate instance because the application will modify the request during |
170 // the application flow (we know it always does because we do ourselves by setting REMOTE_ADDR to 127.0.0.1 | 170 // the application flow (we know it always does because we do ourselves by setting REMOTE_ADDR to 127.0.0.1 |
171 // and adding the X-Forwarded-For header, see HttpCache::forward()). | 171 // and adding the X-Forwarded-For header, see HttpCache::forward()). |
172 $this->request = clone $request; | 172 $this->request = clone $request; |
173 if (null !== $this->surrogate) { | 173 if (null !== $this->surrogate) { |
174 $this->surrogateCacheStrategy = $this->surrogate->createCacheStrategy(); | 174 $this->surrogateCacheStrategy = $this->surrogate->createCacheStrategy(); |
175 } | 175 } |
176 } | 176 } |
177 | 177 |
178 $this->traces[$this->getTraceKey($request)] = array(); | 178 $this->traces[$this->getTraceKey($request)] = []; |
179 | 179 |
180 if (!$request->isMethodSafe(false)) { | 180 if (!$request->isMethodSafe(false)) { |
181 $response = $this->invalidate($request, $catch); | 181 $response = $this->invalidate($request, $catch); |
182 } elseif ($request->headers->has('expect') || !$request->isMethodCacheable()) { | 182 } elseif ($request->headers->has('expect') || !$request->isMethodCacheable()) { |
183 $response = $this->pass($request, $catch); | 183 $response = $this->pass($request, $catch); |
258 if ($response->isSuccessful() || $response->isRedirect()) { | 258 if ($response->isSuccessful() || $response->isRedirect()) { |
259 try { | 259 try { |
260 $this->store->invalidate($request); | 260 $this->store->invalidate($request); |
261 | 261 |
262 // As per the RFC, invalidate Location and Content-Location URLs if present | 262 // As per the RFC, invalidate Location and Content-Location URLs if present |
263 foreach (array('Location', 'Content-Location') as $header) { | 263 foreach (['Location', 'Content-Location'] as $header) { |
264 if ($uri = $response->headers->get($header)) { | 264 if ($uri = $response->headers->get($header)) { |
265 $subRequest = Request::create($uri, 'get', array(), array(), array(), $request->server->all()); | 265 $subRequest = Request::create($uri, 'get', [], [], [], $request->server->all()); |
266 | 266 |
267 $this->store->invalidate($subRequest); | 267 $this->store->invalidate($subRequest); |
268 } | 268 } |
269 } | 269 } |
270 | 270 |
355 $subRequest->headers->set('if_modified_since', $entry->headers->get('Last-Modified')); | 355 $subRequest->headers->set('if_modified_since', $entry->headers->get('Last-Modified')); |
356 | 356 |
357 // Add our cached etag validator to the environment. | 357 // Add our cached etag validator to the environment. |
358 // We keep the etags from the client to handle the case when the client | 358 // We keep the etags from the client to handle the case when the client |
359 // has a different private valid entry which is not cached here. | 359 // has a different private valid entry which is not cached here. |
360 $cachedEtags = $entry->getEtag() ? array($entry->getEtag()) : array(); | 360 $cachedEtags = $entry->getEtag() ? [$entry->getEtag()] : []; |
361 $requestEtags = $request->getETags(); | 361 $requestEtags = $request->getETags(); |
362 if ($etags = array_unique(array_merge($cachedEtags, $requestEtags))) { | 362 if ($etags = array_unique(array_merge($cachedEtags, $requestEtags))) { |
363 $subRequest->headers->set('if_none_match', implode(', ', $etags)); | 363 $subRequest->headers->set('if_none_match', implode(', ', $etags)); |
364 } | 364 } |
365 | 365 |
368 if (304 == $response->getStatusCode()) { | 368 if (304 == $response->getStatusCode()) { |
369 $this->record($request, 'valid'); | 369 $this->record($request, 'valid'); |
370 | 370 |
371 // return the response and not the cache entry if the response is valid but not cached | 371 // return the response and not the cache entry if the response is valid but not cached |
372 $etag = $response->getEtag(); | 372 $etag = $response->getEtag(); |
373 if ($etag && in_array($etag, $requestEtags) && !in_array($etag, $cachedEtags)) { | 373 if ($etag && \in_array($etag, $requestEtags) && !\in_array($etag, $cachedEtags)) { |
374 return $response; | 374 return $response; |
375 } | 375 } |
376 | 376 |
377 $entry = clone $entry; | 377 $entry = clone $entry; |
378 $entry->headers->remove('Date'); | 378 $entry->headers->remove('Date'); |
379 | 379 |
380 foreach (array('Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified') as $name) { | 380 foreach (['Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified'] as $name) { |
381 if ($response->headers->has($name)) { | 381 if ($response->headers->has($name)) { |
382 $entry->headers->set($name, $response->headers->get($name)); | 382 $entry->headers->set($name, $response->headers->get($name)); |
383 } | 383 } |
384 } | 384 } |
385 | 385 |
442 { | 442 { |
443 if ($this->surrogate) { | 443 if ($this->surrogate) { |
444 $this->surrogate->addSurrogateCapability($request); | 444 $this->surrogate->addSurrogateCapability($request); |
445 } | 445 } |
446 | 446 |
447 // modify the X-Forwarded-For header if needed | |
448 $forwardedFor = $request->headers->get('X-Forwarded-For'); | |
449 if ($forwardedFor) { | |
450 $request->headers->set('X-Forwarded-For', $forwardedFor.', '.$request->server->get('REMOTE_ADDR')); | |
451 } else { | |
452 $request->headers->set('X-Forwarded-For', $request->server->get('REMOTE_ADDR')); | |
453 } | |
454 | |
455 // fix the client IP address by setting it to 127.0.0.1 as HttpCache | |
456 // is always called from the same process as the backend. | |
457 $request->server->set('REMOTE_ADDR', '127.0.0.1'); | |
458 | |
459 // make sure HttpCache is a trusted proxy | |
460 if (!in_array('127.0.0.1', $trustedProxies = Request::getTrustedProxies())) { | |
461 $trustedProxies[] = '127.0.0.1'; | |
462 Request::setTrustedProxies($trustedProxies, Request::HEADER_X_FORWARDED_ALL); | |
463 } | |
464 | |
465 // always a "master" request (as the real master request can be in cache) | 447 // always a "master" request (as the real master request can be in cache) |
466 $response = $this->kernel->handle($request, HttpKernelInterface::MASTER_REQUEST, $catch); | 448 $response = SubRequestHandler::handle($this->kernel, $request, HttpKernelInterface::MASTER_REQUEST, $catch); |
467 // FIXME: we probably need to also catch exceptions if raw === true | |
468 | 449 |
469 // we don't implement the stale-if-error on Requests, which is nonetheless part of the RFC | 450 // we don't implement the stale-if-error on Requests, which is nonetheless part of the RFC |
470 if (null !== $entry && in_array($response->getStatusCode(), array(500, 502, 503, 504))) { | 451 if (null !== $entry && \in_array($response->getStatusCode(), [500, 502, 503, 504])) { |
471 if (null === $age = $entry->headers->getCacheControlDirective('stale-if-error')) { | 452 if (null === $age = $entry->headers->getCacheControlDirective('stale-if-error')) { |
472 $age = $this->options['stale_if_error']; | 453 $age = $this->options['stale_if_error']; |
473 } | 454 } |
474 | 455 |
475 if (abs($entry->getTtl()) < $age) { | 456 if (abs($entry->getTtl()) < $age) { |
604 } | 585 } |
605 | 586 |
606 $response->setContent(ob_get_clean()); | 587 $response->setContent(ob_get_clean()); |
607 $response->headers->remove('X-Body-Eval'); | 588 $response->headers->remove('X-Body-Eval'); |
608 if (!$response->headers->has('Transfer-Encoding')) { | 589 if (!$response->headers->has('Transfer-Encoding')) { |
609 $response->headers->set('Content-Length', strlen($response->getContent())); | 590 $response->headers->set('Content-Length', \strlen($response->getContent())); |
610 } | 591 } |
611 } elseif ($response->headers->has('X-Body-File')) { | 592 } elseif ($response->headers->has('X-Body-File')) { |
612 // Response does not include possibly dynamic content (ESI, SSI), so we need | 593 // Response does not include possibly dynamic content (ESI, SSI), so we need |
613 // not handle the content for HEAD requests | 594 // not handle the content for HEAD requests |
614 if (!$request->isMethod('HEAD')) { | 595 if (!$request->isMethod('HEAD')) { |
638 { | 619 { |
639 foreach ($this->options['private_headers'] as $key) { | 620 foreach ($this->options['private_headers'] as $key) { |
640 $key = strtolower(str_replace('HTTP_', '', $key)); | 621 $key = strtolower(str_replace('HTTP_', '', $key)); |
641 | 622 |
642 if ('cookie' === $key) { | 623 if ('cookie' === $key) { |
643 if (count($request->cookies->all())) { | 624 if (\count($request->cookies->all())) { |
644 return true; | 625 return true; |
645 } | 626 } |
646 } elseif ($request->headers->has($key)) { | 627 } elseif ($request->headers->has($key)) { |
647 return true; | 628 return true; |
648 } | 629 } |