/**
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return CacheEntry|null entry to save, null if can't cache it
  */
 protected function getCacheObject(RequestInterface $request, ResponseInterface $response)
 {
     if (!isset($this->statusAccepted[$response->getStatusCode()])) {
         // Don't cache it
         return;
     }
     $cacheControl = new KeyValueHttpHeader($response->getHeader('Cache-Control'));
     $varyHeader = new KeyValueHttpHeader($response->getHeader('Vary'));
     if ($varyHeader->has('*')) {
         // This will never match with a request
         return;
     }
     if ($cacheControl->has('no-store')) {
         // No store allowed (maybe some sensitives data...)
         return;
     }
     if ($cacheControl->has('no-cache')) {
         // Stale response see RFC7234 section 5.2.1.4
         $entry = new CacheEntry($request, $response, new \DateTime('-1 seconds'));
         return $entry->hasValidationInformation() ? $entry : null;
     }
     foreach ($this->ageKey as $key) {
         if ($cacheControl->has($key)) {
             return new CacheEntry($request, $response, new \DateTime('+' . (int) $cacheControl->get($key) . 'seconds'));
         }
     }
     if ($response->hasHeader('Expires')) {
         $expireAt = \DateTime::createFromFormat(\DateTime::RFC1123, $response->getHeaderLine('Expires'));
         if ($expireAt !== false) {
             return new CacheEntry($request, $response, $expireAt);
         }
     }
     return new CacheEntry($request, $response, new \DateTime('-1 seconds'));
 }
 /**
  * @param ResponseInterface $response
  * @return CacheEntry|null entry to save, null if can't cache it
  */
 protected function getCacheObject(ResponseInterface $response)
 {
     if ($response->hasHeader("Cache-Control")) {
         $cacheControlDirectives = $response->getHeader("Cache-Control");
         if (in_array("no-store", $cacheControlDirectives)) {
             // No store allowed (maybe some sensitives data...)
             return null;
         }
         if (in_array("no-cache", $cacheControlDirectives)) {
             // Stale response see RFC7234 section 5.2.1.4
             $entry = new CacheEntry($response, new \DateTime('-1 seconds'));
             return $entry->hasValidationInformation() ? $entry : null;
         }
         $matches = [];
         if (preg_match('/^max-age=([0-9]*)$/', $response->getHeaderLine("Cache-Control"), $matches)) {
             // Handle max-age header
             return new CacheEntry($response, new \DateTime('+' . $matches[1] . 'seconds'));
         }
     }
     if ($response->hasHeader("Expires")) {
         $expireAt = \DateTime::createFromFormat('D, d M Y H:i:s T', $response->getHeaderLine("Expires"));
         if ($expireAt !== FALSE) {
             return new CacheEntry($response, $expireAt);
         }
     }
     return new CacheEntry($response, new \DateTime('1 days ago'));
 }
 /**
  * @param ResponseInterface $response
  * @return CacheEntry|null entry to save, null if can't cache it
  */
 protected function getCacheObject(ResponseInterface $response)
 {
     if ($response->hasHeader("Cache-Control")) {
         $values = new KeyValueHttpHeader($response->getHeader("Cache-Control"));
         if ($values->has('no-store')) {
             // No store allowed (maybe some sensitives data...)
             return null;
         }
         if ($values->has('no-cache')) {
             // Stale response see RFC7234 section 5.2.1.4
             $entry = new CacheEntry($response, new \DateTime('-1 seconds'));
             return $entry->hasValidationInformation() ? $entry : null;
         }
         if ($values->has('max-age')) {
             return new CacheEntry($response, new \DateTime('+' . $values->get('max-age') . 'seconds'));
         }
         return new CacheEntry($response, new \DateTime());
     }
     if ($response->hasHeader("Expires")) {
         $expireAt = \DateTime::createFromFormat('D, d M Y H:i:s T', $response->getHeaderLine("Expires"));
         if ($expireAt !== FALSE) {
             return new CacheEntry($response, $expireAt);
         }
     }
     return new CacheEntry($response, new \DateTime('-1 seconds'));
 }
 /**
  * {@inheritdoc}
  */
 public function save($key, CacheEntry $data)
 {
     try {
         $lifeTime = $data->getTTL();
         if ($lifeTime >= 0) {
             return $this->cache->save($key, gzcompress(serialize($data)), $lifeTime);
         }
     } catch (\Exception $ignored) {
         // No fail if we can't save it the storage
     }
     return false;
 }
 /**
  * @param ResponseInterface $response
  * @param KeyValueHttpHeader $cacheControl
  * @return CacheEntry|null
  */
 protected function getCacheObjectForCacheControl(ResponseInterface $response, KeyValueHttpHeader $cacheControl)
 {
     if ($cacheControl->has('no-store')) {
         // No store allowed (maybe some sensitives data...)
         return null;
     }
     if ($cacheControl->has('no-cache')) {
         // Stale response see RFC7234 section 5.2.1.4
         $entry = new CacheEntry($response, new \DateTime('-1 seconds'));
         return $entry->hasValidationInformation() ? $entry : null;
     }
     if ($cacheControl->has('max-age')) {
         return new CacheEntry($response, new \DateTime('+' . (int) $cacheControl->get('max-age') . 'seconds'));
     }
     return new CacheEntry($response, new \DateTime());
 }
 /**
  * {@inheritdoc}
  */
 public function save($key, CacheEntry $data)
 {
     try {
         $lifeTime = $data->getTTL();
         if ($lifeTime === 0) {
             return $this->cache->forever($key, serialize($data));
         } else {
             if ($lifeTime > 0) {
                 return $this->cache->add($key, serialize($data), $lifeTime);
             }
         }
     } catch (\Exception $ignored) {
         // No fail if we can't save it the storage
     }
     return false;
 }
 /**
  * @param RequestInterface $request
  * @param CacheEntry       $cacheEntry
  *
  * @return RequestInterface
  */
 protected static function getRequestWithReValidationHeader(RequestInterface $request, CacheEntry $cacheEntry)
 {
     if ($cacheEntry->getResponse()->hasHeader('Last-Modified')) {
         $request = $request->withHeader('If-Modified-Since', $cacheEntry->getResponse()->getHeader('Last-Modified'));
     }
     if ($cacheEntry->getResponse()->hasHeader('Etag')) {
         $request = $request->withHeader('If-None-Match', $cacheEntry->getResponse()->getHeader('Etag'));
     }
     return $request;
 }
 /**
  * @param RequestInterface $request
  * @param CacheStorageInterface $cacheStorage
  * @param CacheEntry $cacheEntry
  * @return bool if added
  */
 protected static function addReValidationRequest(RequestInterface $request, CacheStorageInterface &$cacheStorage, CacheEntry $cacheEntry)
 {
     // Add the promise for revalidate
     if (static::$client !== null) {
         /** @var RequestInterface $request */
         $request = $request->withHeader("X-ReValidation", "1");
         static::$waitingRevalidate[] = static::$client->sendAsync($request)->then(function (ResponseInterface $response) use($request, &$cacheStorage, $cacheEntry) {
             if ($response->getStatusCode() == 304) {
                 // Not modified => cache entry is re-validate
                 /** @var ResponseInterface $response */
                 $response = $response->withStatus($cacheEntry->getResponse()->getStatusCode());
                 $response = $response->withBody($cacheEntry->getResponse()->getBody());
             }
             $cacheStorage->cache($request, $response);
         });
         return true;
     }
     return false;
 }