public function testCacheProvider()
 {
     $TMP_DIR = __DIR__ . '/tmp/';
     $cacheProviders = [new ArrayCache(), new ChainCache([new ArrayCache()]), new FilesystemCache($TMP_DIR), new PhpFileCache($TMP_DIR)];
     $request = new Request('GET', 'test.local');
     $response = new Response(200, ['Cache-Control' => 'max-age=60'], 'Test content');
     /** @var CacheProvider $cacheProvider */
     foreach ($cacheProviders as $cacheProvider) {
         $this->rrmdir($TMP_DIR);
         $cache = new PrivateCache($cacheProvider);
         $cache->cache($request, $response);
         $entry = $cache->fetch($request);
         $this->assertNotNull($entry);
         $this->assertEquals((string) $response->getBody(), (string) $entry->getResponse()->getBody());
     }
     $this->rrmdir($TMP_DIR);
 }
 /**
  * @param CacheStorageInterface $cacheStorage
  * @return \Closure the Middleware for Guzzle HandlerStack
  */
 public static function getMiddleware(CacheStorageInterface $cacheStorage = null)
 {
     if ($cacheStorage === null) {
         $cacheStorage = new PrivateCache();
     }
     register_shutdown_function(['Kevinrob\\GuzzleCache\\CacheMiddleware', 'purgeReValidation']);
     return function (callable $handler) use(&$cacheStorage) {
         return function (RequestInterface $request, array $options) use($handler, &$cacheStorage) {
             $reqMethod = $request->getMethod();
             if ($reqMethod !== 'GET' && $reqMethod !== 'HEAD') {
                 // No caching for others methods
                 return $handler($request, $options);
             }
             if ($request->hasHeader("X-ReValidation")) {
                 return $handler($request->withoutHeader("X-ReValidation"), $options);
             }
             // If cache => return new FulfilledPromise(...) with response
             $cacheEntry = $cacheStorage->fetch($request);
             if ($cacheEntry instanceof CacheEntry) {
                 if ($cacheEntry->isFresh()) {
                     // Cache HIT!
                     return new FulfilledPromise($cacheEntry->getResponse()->withHeader("X-Cache", "HIT"));
                 } elseif ($cacheEntry->hasValidationInformation()) {
                     // Re-validation header
                     $request = static::getRequestWithReValidationHeader($request, $cacheEntry);
                     if ($cacheEntry->staleWhileValidate()) {
                         static::addReValidationRequest($request, $cacheStorage, $cacheEntry);
                         return new FulfilledPromise($cacheEntry->getResponse()->withHeader("X-Cache", "Stale while revalidate"));
                     }
                 }
             }
             /** @var Promise $promise */
             $promise = $handler($request, $options);
             return $promise->then(function (ResponseInterface $response) use($request, &$cacheStorage, $cacheEntry) {
                 if ($response->getStatusCode() >= 500) {
                     $responseStale = static::getStaleResponse($cacheEntry);
                     if ($responseStale instanceof ResponseInterface) {
                         return $responseStale;
                     }
                 }
                 if ($response->getStatusCode() == 304 && $cacheEntry instanceof CacheEntry) {
                     // Not modified => cache entry is re-validate
                     /** @var ResponseInterface $response */
                     $response = $response->withStatus($cacheEntry->getResponse()->getStatusCode())->withHeader("X-Cache", "HIT with validation");
                     $response = $response->withBody($cacheEntry->getResponse()->getBody());
                 }
                 // Add to the cache
                 $cacheStorage->cache($request, $response);
                 return $response;
             }, function (\Exception $ex) use($cacheEntry) {
                 if ($ex instanceof TransferException) {
                     $response = static::getStaleResponse($cacheEntry);
                     if ($response instanceof ResponseInterface) {
                         return $response;
                     }
                 }
                 throw $ex;
             });
         };
     };
 }