41 $currentTime = time();
43 $overrideTtl = $request->
getParams()->get(
'cache.override_ttl');
47 $maxAge = $response->getMaxAge();
48 if ($maxAge !==
null) {
55 if ($cacheControl = $response->getHeader(
'Cache-Control')) {
56 $stale = $cacheControl->getDirective(
'stale-if-error');
57 if ($stale ===
true) {
59 }
else if (is_numeric($stale)) {
66 $persistedRequest = $this->persistHeaders($request);
69 if ($manifest = $this->
cache->fetch($key)) {
71 $vary = $response->getVary();
72 foreach (unserialize($manifest) as $entry) {
74 if ($entry[4] < $currentTime) {
77 $entry[1][
'vary'] = isset($entry[1][
'vary']) ? $entry[1][
'vary'] :
'';
78 if ($vary != $entry[1][
'vary'] || !$this->requestsMatch($vary, $entry[0], $persistedRequest)) {
86 if ($response->getBody() && $response->getBody()->getContentLength() > 0) {
88 $this->
cache->save($bodyDigest, (
string) $response->getBody(), $ttl);
91 array_unshift($entries, array(
93 $this->persistHeaders($response),
94 $response->getStatusCode(),
99 $this->
cache->save($key, serialize($entries));
102 public function delete(RequestInterface $request)
105 if ($entries = $this->
cache->fetch($key)) {
107 foreach (unserialize($entries) as $entry) {
109 $this->
cache->delete($entry[3]);
112 $this->
cache->delete($key);
116 public function purge($url)
118 foreach (array(
'GET',
'HEAD',
'POST',
'PUT',
'DELETE') as $method) {
119 $this->
delete(
new Request($method, $url));
123 public function fetch(RequestInterface $request)
126 if (!($entries = $this->
cache->fetch($key))) {
131 $headers = $this->persistHeaders($request);
132 $entries = unserialize($entries);
133 foreach ($entries as $index => $entry) {
134 if ($this->requestsMatch(isset($entry[1][
'vary']) ? $entry[1][
'vary'] :
'', $headers, $entry[0])) {
146 if ($match[4] < time()) {
149 $response =
new Response($match[2], $match[1]);
151 if ($body = $this->
cache->fetch($match[3])) {
152 $response->setBody($body);
160 if ($response === -1) {
162 unset($entries[$index]);
164 $this->
cache->save($key, serialize($entries));
166 $this->
cache->delete($key);
181 protected function getCacheKey(RequestInterface $request)
184 if ($filter = $request->getParams()->get(
'cache.key_filter')) {
185 $url = $request->getUrl(
true);
186 foreach (explode(
',', $filter) as $remove) {
187 $url->getQuery()->remove(trim($remove));
190 $url = $request->getUrl();
193 return $this->keyPrefix . md5($request->getMethod() .
' ' . $url);
204 protected function getBodyKey($url, EntityBodyInterface $body)
206 return $this->keyPrefix . md5($url) . $body->getContentMd5();
218 private function requestsMatch($vary, $r1, $r2)
221 foreach (explode(
',', $vary) as $header) {
222 $key = trim(strtolower($header));
223 $v1 = isset($r1[$key]) ? $r1[$key] :
null;
224 $v2 = isset($r2[$key]) ? $r2[$key] :
null;
241 private function persistHeaders(MessageInterface $message)
244 static $noCache = array(
246 'connection' =>
true,
247 'keep-alive' =>
true,
248 'proxy-authenticate' =>
true,
249 'proxy-authorization' =>
true,
252 'transfer-encoding' =>
true,
254 'set-cookie' =>
true,
255 'set-cookie2' =>
true
259 $headers = $message->getHeaders()->getAll();
260 $headers = array_diff_key($headers, $noCache);
262 $headers = array_map(
function ($h) {
return (
string) $h; }, $headers);