From a0192c0d54bacbde8606d1aeae701be6454903c7 Mon Sep 17 00:00:00 2001 From: iconnor Date: Mon, 15 Jan 2018 11:30:53 -0600 Subject: [PATCH 01/17] Adding response mutator. --- src/CachePlugin.php | 38 ++++++++++++++++++++---- src/Mutator/AddHeaderResponseMutator.php | 37 +++++++++++++++++++++++ src/Mutator/ResponseMutator.php | 23 ++++++++++++++ 3 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 src/Mutator/AddHeaderResponseMutator.php create mode 100644 src/Mutator/ResponseMutator.php diff --git a/src/CachePlugin.php b/src/CachePlugin.php index 166cf9b..39a6eb9 100644 --- a/src/CachePlugin.php +++ b/src/CachePlugin.php @@ -6,6 +6,7 @@ use Http\Client\Common\Plugin\Exception\RewindStreamException; use Http\Client\Common\Plugin\Cache\Generator\CacheKeyGenerator; use Http\Client\Common\Plugin\Cache\Generator\SimpleGenerator; +use Http\Client\Common\Plugin\Cache\Mutator\ResponseMutator; use Http\Message\StreamFactory; use Http\Promise\FulfilledPromise; use Psr\Cache\CacheItemInterface; @@ -59,6 +60,7 @@ final class CachePlugin implements Plugin * @var array $methods list of request methods which can be cached * @var array $respect_response_cache_directives list of cache directives this plugin will respect while caching responses * @var CacheKeyGenerator $cache_key_generator an object to generate the cache key. Defaults to a new instance of SimpleGenerator + * @var ResponseMutator $response_mutator an object to mutate the response based on the results of the cache check. Defaults to nothing * } */ public function __construct(CacheItemPoolInterface $pool, StreamFactory $streamFactory, array $config = []) @@ -129,7 +131,11 @@ public function handleRequest(RequestInterface $request, callable $next, callabl $method = strtoupper($request->getMethod()); // if the request not is cachable, move to $next if (!in_array($method, $this->config['methods'])) { - return $next($request); + return $next($request)->then(function (ResponseInterface $response) { + $response = $this->handleResponseMutator($response, false); + + return $response; + }); } // If we can cache the request @@ -141,7 +147,10 @@ public function handleRequest(RequestInterface $request, callable $next, callabl // The array_key_exists() is to be removed in 2.0. if (array_key_exists('expiresAt', $data) && (null === $data['expiresAt'] || time() < $data['expiresAt'])) { // This item is still valid according to previous cache headers - return new FulfilledPromise($this->createResponseFromCacheItem($cacheItem)); + $response = $this->createResponseFromCacheItem($cacheItem); + $response = $this->handleResponseMutator($response, true); + + return new FulfilledPromise($response); } // Add headers to ask the server if this cache is still valid @@ -161,7 +170,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl * We do not have the item in cache. This plugin did not add If-Modified-Since * or If-None-Match headers. Return the response from server. */ - return $response; + return $$this->handleResponseMutator($response, false); } // The cached response we have is still valid @@ -171,7 +180,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl $cacheItem->set($data)->expiresAfter($this->calculateCacheItemExpiresAfter($maxAge)); $this->pool->save($cacheItem); - return $this->createResponseFromCacheItem($cacheItem); + return $this->handleResponseMutator($this->createResponseFromCacheItem($cacheItem), true); } if ($this->isCacheable($response)) { @@ -196,7 +205,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl $this->pool->save($cacheItem); } - return $response; + return $this->handleResponseMutator($response, false); }); } @@ -343,6 +352,7 @@ private function configureOptions(OptionsResolver $resolver) 'methods' => ['GET', 'HEAD'], 'respect_response_cache_directives' => ['no-cache', 'private', 'max-age', 'no-store'], 'cache_key_generator' => null, + 'response_mutator' => null, ]); $resolver->setAllowedTypes('cache_lifetime', ['int', 'null']); @@ -357,6 +367,7 @@ private function configureOptions(OptionsResolver $resolver) return empty($matches); }); + $resolver->setAllowedTypes('response_mutator', ['null', 'Http\Client\Common\Plugin\Cache\Mutator\ResponseMutator']); $resolver->setNormalizer('respect_cache_headers', function (Options $options, $value) { if (null !== $value) { @@ -441,4 +452,21 @@ private function getETag(CacheItemInterface $cacheItem) } } } + + /** + * Call the reponse mutator, if one is set. + * + * @param ResponseInterface $response + * @param bool $cacheHit + * + * @return ResponseInterface + */ + private function handleResponseMutator(ResponseInterface $response, $cacheHit) + { + if (null !== $this->config['response_mutator']) { + $response = $this->config['response_mutator']->mutate($response, $cacheHit); + } + + return $response; + } } diff --git a/src/Mutator/AddHeaderResponseMutator.php b/src/Mutator/AddHeaderResponseMutator.php new file mode 100644 index 0000000..324cb58 --- /dev/null +++ b/src/Mutator/AddHeaderResponseMutator.php @@ -0,0 +1,37 @@ + + */ +class AddHeaderResponseMutator implements ResponseMutator +{ + /** @var string */ + private $headerName; + + /** + * @param string $headerName + */ + public function __construct($headerName) + { + $this->headerName = $headerName; + } + + /** + * Mutate the response depending on the cache status. + * + * @param ResponseInterface $response + * @param bool $cacheHit + * + * @return string + */ + public function mutate(ResponseInterface $response, $cacheHit) + { + return $response->withHeader($this->headerName, $cacheHit); + } +} diff --git a/src/Mutator/ResponseMutator.php b/src/Mutator/ResponseMutator.php new file mode 100644 index 0000000..e400994 --- /dev/null +++ b/src/Mutator/ResponseMutator.php @@ -0,0 +1,23 @@ + + */ +interface ResponseMutator +{ + /** + * Mutate the response depending on the cache status. + * + * @param ResponseInterface $response + * @param bool $cacheHit + * + * @return string + */ + public function mutate(ResponseInterface $response, $cacheHit); +} From 8abb28a7ca3ba6ea5ab7140af9ccdfaf4c2e659c Mon Sep 17 00:00:00 2001 From: iconnor Date: Mon, 15 Jan 2018 11:44:45 -0600 Subject: [PATCH 02/17] Fixing style. --- src/CachePlugin.php | 2 +- src/Mutator/AddHeaderResponseMutator.php | 2 +- src/Mutator/ResponseMutator.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CachePlugin.php b/src/CachePlugin.php index 39a6eb9..5bdb673 100644 --- a/src/CachePlugin.php +++ b/src/CachePlugin.php @@ -457,7 +457,7 @@ private function getETag(CacheItemInterface $cacheItem) * Call the reponse mutator, if one is set. * * @param ResponseInterface $response - * @param bool $cacheHit + * @param bool $cacheHit * * @return ResponseInterface */ diff --git a/src/Mutator/AddHeaderResponseMutator.php b/src/Mutator/AddHeaderResponseMutator.php index 324cb58..165f9fc 100644 --- a/src/Mutator/AddHeaderResponseMutator.php +++ b/src/Mutator/AddHeaderResponseMutator.php @@ -26,7 +26,7 @@ public function __construct($headerName) * Mutate the response depending on the cache status. * * @param ResponseInterface $response - * @param bool $cacheHit + * @param bool $cacheHit * * @return string */ diff --git a/src/Mutator/ResponseMutator.php b/src/Mutator/ResponseMutator.php index e400994..f44fa8d 100644 --- a/src/Mutator/ResponseMutator.php +++ b/src/Mutator/ResponseMutator.php @@ -15,7 +15,7 @@ interface ResponseMutator * Mutate the response depending on the cache status. * * @param ResponseInterface $response - * @param bool $cacheHit + * @param bool $cacheHit * * @return string */ From 63f438f54c98b5e152459c65083f59699f4208ca Mon Sep 17 00:00:00 2001 From: iconnor Date: Mon, 15 Jan 2018 11:55:57 -0600 Subject: [PATCH 03/17] Adding default value to header. --- src/Mutator/AddHeaderResponseMutator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mutator/AddHeaderResponseMutator.php b/src/Mutator/AddHeaderResponseMutator.php index 165f9fc..af33d59 100644 --- a/src/Mutator/AddHeaderResponseMutator.php +++ b/src/Mutator/AddHeaderResponseMutator.php @@ -17,7 +17,7 @@ class AddHeaderResponseMutator implements ResponseMutator /** * @param string $headerName */ - public function __construct($headerName) + public function __construct($headerName = 'X-From-Php-Http-Cache') { $this->headerName = $headerName; } From 465c0e43809d50c08aa5e9e72195c2ba1900df08 Mon Sep 17 00:00:00 2001 From: iconnor Date: Mon, 15 Jan 2018 12:22:01 -0600 Subject: [PATCH 04/17] Adding request to callback. --- src/CachePlugin.php | 19 ++++++++++--------- src/Mutator/AddHeaderResponseMutator.php | 3 ++- src/Mutator/ResponseMutator.php | 4 +++- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/CachePlugin.php b/src/CachePlugin.php index 5bdb673..acf8187 100644 --- a/src/CachePlugin.php +++ b/src/CachePlugin.php @@ -131,8 +131,8 @@ public function handleRequest(RequestInterface $request, callable $next, callabl $method = strtoupper($request->getMethod()); // if the request not is cachable, move to $next if (!in_array($method, $this->config['methods'])) { - return $next($request)->then(function (ResponseInterface $response) { - $response = $this->handleResponseMutator($response, false); + return $next($request)->then(function (ResponseInterface $response) use ($request) { + $response = $this->handleResponseMutator($request, $response, false); return $response; }); @@ -148,7 +148,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl if (array_key_exists('expiresAt', $data) && (null === $data['expiresAt'] || time() < $data['expiresAt'])) { // This item is still valid according to previous cache headers $response = $this->createResponseFromCacheItem($cacheItem); - $response = $this->handleResponseMutator($response, true); + $response = $this->handleResponseMutator($request, $response, true); return new FulfilledPromise($response); } @@ -163,14 +163,14 @@ public function handleRequest(RequestInterface $request, callable $next, callabl } } - return $next($request)->then(function (ResponseInterface $response) use ($cacheItem) { + return $next($request)->then(function (ResponseInterface $response) use ($request, $cacheItem) { if (304 === $response->getStatusCode()) { if (!$cacheItem->isHit()) { /* * We do not have the item in cache. This plugin did not add If-Modified-Since * or If-None-Match headers. Return the response from server. */ - return $$this->handleResponseMutator($response, false); + return $this->handleResponseMutator($request, $response, false); } // The cached response we have is still valid @@ -180,7 +180,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl $cacheItem->set($data)->expiresAfter($this->calculateCacheItemExpiresAfter($maxAge)); $this->pool->save($cacheItem); - return $this->handleResponseMutator($this->createResponseFromCacheItem($cacheItem), true); + return $this->handleResponseMutator($request, $this->createResponseFromCacheItem($cacheItem), true); } if ($this->isCacheable($response)) { @@ -205,7 +205,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl $this->pool->save($cacheItem); } - return $this->handleResponseMutator($response, false); + return $this->handleResponseMutator($request, $response, false); }); } @@ -456,15 +456,16 @@ private function getETag(CacheItemInterface $cacheItem) /** * Call the reponse mutator, if one is set. * + * @param RequestInterface $request * @param ResponseInterface $response * @param bool $cacheHit * * @return ResponseInterface */ - private function handleResponseMutator(ResponseInterface $response, $cacheHit) + private function handleResponseMutator(RequestInterface $request, ResponseInterface $response, $cacheHit) { if (null !== $this->config['response_mutator']) { - $response = $this->config['response_mutator']->mutate($response, $cacheHit); + $response = $this->config['response_mutator']->mutate($request, $response, $cacheHit); } return $response; diff --git a/src/Mutator/AddHeaderResponseMutator.php b/src/Mutator/AddHeaderResponseMutator.php index af33d59..1856505 100644 --- a/src/Mutator/AddHeaderResponseMutator.php +++ b/src/Mutator/AddHeaderResponseMutator.php @@ -2,6 +2,7 @@ namespace Http\Client\Common\Plugin\Cache\Mutator; +use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; /** @@ -30,7 +31,7 @@ public function __construct($headerName = 'X-From-Php-Http-Cache') * * @return string */ - public function mutate(ResponseInterface $response, $cacheHit) + public function mutate(RequestInterface $request, ResponseInterface $response, $cacheHit) { return $response->withHeader($this->headerName, $cacheHit); } diff --git a/src/Mutator/ResponseMutator.php b/src/Mutator/ResponseMutator.php index f44fa8d..bf9c86d 100644 --- a/src/Mutator/ResponseMutator.php +++ b/src/Mutator/ResponseMutator.php @@ -2,6 +2,7 @@ namespace Http\Client\Common\Plugin\Cache\Mutator; +use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; /** @@ -14,10 +15,11 @@ interface ResponseMutator /** * Mutate the response depending on the cache status. * + * @param RequestInterface $request * @param ResponseInterface $response * @param bool $cacheHit * * @return string */ - public function mutate(ResponseInterface $response, $cacheHit); + public function mutate(RequestInterface $request, ResponseInterface $response, $cacheHit); } From f62329e9df40dae58dabb022fdf1d4e189488c1c Mon Sep 17 00:00:00 2001 From: iconnor Date: Mon, 15 Jan 2018 16:35:44 -0600 Subject: [PATCH 05/17] Moving directory --- src/{ => Cache}/Mutator/AddHeaderResponseMutator.php | 0 src/{ => Cache}/Mutator/ResponseMutator.php | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/{ => Cache}/Mutator/AddHeaderResponseMutator.php (100%) rename src/{ => Cache}/Mutator/ResponseMutator.php (100%) diff --git a/src/Mutator/AddHeaderResponseMutator.php b/src/Cache/Mutator/AddHeaderResponseMutator.php similarity index 100% rename from src/Mutator/AddHeaderResponseMutator.php rename to src/Cache/Mutator/AddHeaderResponseMutator.php diff --git a/src/Mutator/ResponseMutator.php b/src/Cache/Mutator/ResponseMutator.php similarity index 100% rename from src/Mutator/ResponseMutator.php rename to src/Cache/Mutator/ResponseMutator.php From a968e8f319209035702ec166d38955acb4095bea Mon Sep 17 00:00:00 2001 From: iconnor Date: Tue, 16 Jan 2018 08:56:30 -0600 Subject: [PATCH 06/17] Renaming default header and values. --- src/Cache/Mutator/AddHeaderResponseMutator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Cache/Mutator/AddHeaderResponseMutator.php b/src/Cache/Mutator/AddHeaderResponseMutator.php index 1856505..4ff97b0 100644 --- a/src/Cache/Mutator/AddHeaderResponseMutator.php +++ b/src/Cache/Mutator/AddHeaderResponseMutator.php @@ -18,7 +18,7 @@ class AddHeaderResponseMutator implements ResponseMutator /** * @param string $headerName */ - public function __construct($headerName = 'X-From-Php-Http-Cache') + public function __construct($headerName = 'X-Cache') { $this->headerName = $headerName; } @@ -33,6 +33,6 @@ public function __construct($headerName = 'X-From-Php-Http-Cache') */ public function mutate(RequestInterface $request, ResponseInterface $response, $cacheHit) { - return $response->withHeader($this->headerName, $cacheHit); + return $response->withHeader($this->headerName, $cacheHit ? 'HIT' : 'MISS'); } } From 884c87ce53bb95c26de5af78fdd2b47be80f61f8 Mon Sep 17 00:00:00 2001 From: iconnor Date: Tue, 16 Jan 2018 09:02:04 -0600 Subject: [PATCH 07/17] Pass through cache item as well. --- .../Mutator/AddHeaderResponseMutator.php | 9 +++++--- src/Cache/Mutator/ResponseMutator.php | 10 +++++---- src/CachePlugin.php | 21 ++++++++++--------- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/Cache/Mutator/AddHeaderResponseMutator.php b/src/Cache/Mutator/AddHeaderResponseMutator.php index 4ff97b0..379727f 100644 --- a/src/Cache/Mutator/AddHeaderResponseMutator.php +++ b/src/Cache/Mutator/AddHeaderResponseMutator.php @@ -4,6 +4,7 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; +use Psr\Cache\CacheItemPoolInterface; /** * Adds a header if the response came from cache. @@ -26,12 +27,14 @@ public function __construct($headerName = 'X-Cache') /** * Mutate the response depending on the cache status. * - * @param ResponseInterface $response - * @param bool $cacheHit + * @param RequestInterface $request + * @param ResponseInterface $response + * @param bool $cacheHit + * @param CacheItemInterface|null $cacheItem * * @return string */ - public function mutate(RequestInterface $request, ResponseInterface $response, $cacheHit) + public function mutate(RequestInterface $request, ResponseInterface $response, $cacheHit, CacheItemInterface $cacheItem) { return $response->withHeader($this->headerName, $cacheHit ? 'HIT' : 'MISS'); } diff --git a/src/Cache/Mutator/ResponseMutator.php b/src/Cache/Mutator/ResponseMutator.php index bf9c86d..bf530f3 100644 --- a/src/Cache/Mutator/ResponseMutator.php +++ b/src/Cache/Mutator/ResponseMutator.php @@ -4,6 +4,7 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; +use Psr\Cache\CacheItemPoolInterface; /** * An interface for a mutator of a possibly cached response. @@ -15,11 +16,12 @@ interface ResponseMutator /** * Mutate the response depending on the cache status. * - * @param RequestInterface $request - * @param ResponseInterface $response - * @param bool $cacheHit + * @param RequestInterface $request + * @param ResponseInterface $response + * @param bool $cacheHit + * @param CacheItemInterface|null $cacheItem * * @return string */ - public function mutate(RequestInterface $request, ResponseInterface $response, $cacheHit); + public function mutate(RequestInterface $request, ResponseInterface $response, $cacheHit, CacheItemInterface $cacheItem); } diff --git a/src/CachePlugin.php b/src/CachePlugin.php index acf8187..f24339c 100644 --- a/src/CachePlugin.php +++ b/src/CachePlugin.php @@ -132,7 +132,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl // if the request not is cachable, move to $next if (!in_array($method, $this->config['methods'])) { return $next($request)->then(function (ResponseInterface $response) use ($request) { - $response = $this->handleResponseMutator($request, $response, false); + $response = $this->handleResponseMutator($request, $response, false, null); return $response; }); @@ -148,7 +148,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl if (array_key_exists('expiresAt', $data) && (null === $data['expiresAt'] || time() < $data['expiresAt'])) { // This item is still valid according to previous cache headers $response = $this->createResponseFromCacheItem($cacheItem); - $response = $this->handleResponseMutator($request, $response, true); + $response = $this->handleResponseMutator($request, $response, true, $cacheItem); return new FulfilledPromise($response); } @@ -170,7 +170,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl * We do not have the item in cache. This plugin did not add If-Modified-Since * or If-None-Match headers. Return the response from server. */ - return $this->handleResponseMutator($request, $response, false); + return $this->handleResponseMutator($request, $response, false, $cacheItem); } // The cached response we have is still valid @@ -180,7 +180,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl $cacheItem->set($data)->expiresAfter($this->calculateCacheItemExpiresAfter($maxAge)); $this->pool->save($cacheItem); - return $this->handleResponseMutator($request, $this->createResponseFromCacheItem($cacheItem), true); + return $this->handleResponseMutator($request, $this->createResponseFromCacheItem($cacheItem), true, $cacheItem); } if ($this->isCacheable($response)) { @@ -205,7 +205,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl $this->pool->save($cacheItem); } - return $this->handleResponseMutator($request, $response, false); + return $this->handleResponseMutator($request, $response, false, null); }); } @@ -456,16 +456,17 @@ private function getETag(CacheItemInterface $cacheItem) /** * Call the reponse mutator, if one is set. * - * @param RequestInterface $request - * @param ResponseInterface $response - * @param bool $cacheHit + * @param RequestInterface $request + * @param ResponseInterface $response + * @param bool $cacheHit + * @param CacheItemInterface|null $cacheItem * * @return ResponseInterface */ - private function handleResponseMutator(RequestInterface $request, ResponseInterface $response, $cacheHit) + private function handleResponseMutator(RequestInterface $request, ResponseInterface $response, $cacheHit, CacheItemInterface $cacheItem) { if (null !== $this->config['response_mutator']) { - $response = $this->config['response_mutator']->mutate($request, $response, $cacheHit); + $response = $this->config['response_mutator']->mutate($request, $response, $cacheHit, $cacheItem); } return $response; From 0e5159fc26364e2e9cb8201118b6d166bd47c54c Mon Sep 17 00:00:00 2001 From: iconnor Date: Tue, 16 Jan 2018 09:20:15 -0600 Subject: [PATCH 08/17] Adding support for multiple listeners and renaming. --- .../AddHeaderCacheListener.php} | 13 ++++---- src/Cache/Listener/CacheListener.php | 30 +++++++++++++++++++ src/Cache/Mutator/ResponseMutator.php | 27 ----------------- 3 files changed, 37 insertions(+), 33 deletions(-) rename src/Cache/{Mutator/AddHeaderResponseMutator.php => Listener/AddHeaderCacheListener.php} (51%) create mode 100644 src/Cache/Listener/CacheListener.php delete mode 100644 src/Cache/Mutator/ResponseMutator.php diff --git a/src/Cache/Mutator/AddHeaderResponseMutator.php b/src/Cache/Listener/AddHeaderCacheListener.php similarity index 51% rename from src/Cache/Mutator/AddHeaderResponseMutator.php rename to src/Cache/Listener/AddHeaderCacheListener.php index 379727f..3c17921 100644 --- a/src/Cache/Mutator/AddHeaderResponseMutator.php +++ b/src/Cache/Listener/AddHeaderCacheListener.php @@ -1,17 +1,17 @@ */ -class AddHeaderResponseMutator implements ResponseMutator +class AddHeaderCacheListener implements CacheListener { /** @var string */ private $headerName; @@ -25,16 +25,17 @@ public function __construct($headerName = 'X-Cache') } /** - * Mutate the response depending on the cache status. + * Called before the cache plugin returns the response, with information on whether that response came from cache. * * @param RequestInterface $request * @param ResponseInterface $response - * @param bool $cacheHit + * @param bool $fromCache Whether the `$response` was from the cache or not. + * Note that checking `$cacheItem->isHit()` is not sufficent to determine this. * @param CacheItemInterface|null $cacheItem * * @return string */ - public function mutate(RequestInterface $request, ResponseInterface $response, $cacheHit, CacheItemInterface $cacheItem) + public function onCacheResponse(RequestInterface $request, ResponseInterface $response, $fromCache, CacheItemInterface $cacheItem) { return $response->withHeader($this->headerName, $cacheHit ? 'HIT' : 'MISS'); } diff --git a/src/Cache/Listener/CacheListener.php b/src/Cache/Listener/CacheListener.php new file mode 100644 index 0000000..23f3f21 --- /dev/null +++ b/src/Cache/Listener/CacheListener.php @@ -0,0 +1,30 @@ + + */ +interface CacheListener +{ + /** + * Called before the cache plugin returns the response, with information on whether that response came from cache. + * + * @param RequestInterface $request + * @param ResponseInterface $response + * @param bool $fromCache Whether the `$response` was from the cache or not. + * Note that checking `$cacheItem->isHit()` is not sufficent to determine this. + * @param CacheItemInterface|null $cacheItem + * + * @return string + */ + public function onCacheResponse(RequestInterface $request, ResponseInterface $response, $fromCache, CacheItemInterface $cacheItem); +} diff --git a/src/Cache/Mutator/ResponseMutator.php b/src/Cache/Mutator/ResponseMutator.php deleted file mode 100644 index bf530f3..0000000 --- a/src/Cache/Mutator/ResponseMutator.php +++ /dev/null @@ -1,27 +0,0 @@ - - */ -interface ResponseMutator -{ - /** - * Mutate the response depending on the cache status. - * - * @param RequestInterface $request - * @param ResponseInterface $response - * @param bool $cacheHit - * @param CacheItemInterface|null $cacheItem - * - * @return string - */ - public function mutate(RequestInterface $request, ResponseInterface $response, $cacheHit, CacheItemInterface $cacheItem); -} From fef55cfe05d7c5cff345ecb411d1ef30469d9330 Mon Sep 17 00:00:00 2001 From: iconnor Date: Tue, 16 Jan 2018 09:23:05 -0600 Subject: [PATCH 09/17] Whoops wrong class. --- src/Cache/Listener/CacheListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cache/Listener/CacheListener.php b/src/Cache/Listener/CacheListener.php index 23f3f21..aeb0a8d 100644 --- a/src/Cache/Listener/CacheListener.php +++ b/src/Cache/Listener/CacheListener.php @@ -4,7 +4,7 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; -use Psr\Cache\CacheItemPoolInterface; +use Psr\Cache\CacheItemInterface; /** * Called by the cache plugin with information on the cache status. From e1e4becd2b9c28142bccb185a7554548b7d6c9fd Mon Sep 17 00:00:00 2001 From: iconnor Date: Tue, 16 Jan 2018 09:24:26 -0600 Subject: [PATCH 10/17] Whoops wrong class. --- src/Cache/Listener/AddHeaderCacheListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cache/Listener/AddHeaderCacheListener.php b/src/Cache/Listener/AddHeaderCacheListener.php index 3c17921..91907d0 100644 --- a/src/Cache/Listener/AddHeaderCacheListener.php +++ b/src/Cache/Listener/AddHeaderCacheListener.php @@ -4,7 +4,7 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; -use Psr\Cache\CacheItemPoolInterface; +use Psr\Cache\CacheItemInterface; /** * Adds a header indicating if the response came from cache. From c29b205371f01caf565b2ff64157ca5bdeb3f16d Mon Sep 17 00:00:00 2001 From: iconnor Date: Tue, 16 Jan 2018 09:25:59 -0600 Subject: [PATCH 11/17] Finishing rename. --- src/CachePlugin.php | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/CachePlugin.php b/src/CachePlugin.php index f24339c..4f541be 100644 --- a/src/CachePlugin.php +++ b/src/CachePlugin.php @@ -6,7 +6,7 @@ use Http\Client\Common\Plugin\Exception\RewindStreamException; use Http\Client\Common\Plugin\Cache\Generator\CacheKeyGenerator; use Http\Client\Common\Plugin\Cache\Generator\SimpleGenerator; -use Http\Client\Common\Plugin\Cache\Mutator\ResponseMutator; +use Http\Client\Common\Plugin\Cache\Listener\CacheListener; use Http\Message\StreamFactory; use Http\Promise\FulfilledPromise; use Psr\Cache\CacheItemInterface; @@ -60,7 +60,8 @@ final class CachePlugin implements Plugin * @var array $methods list of request methods which can be cached * @var array $respect_response_cache_directives list of cache directives this plugin will respect while caching responses * @var CacheKeyGenerator $cache_key_generator an object to generate the cache key. Defaults to a new instance of SimpleGenerator - * @var ResponseMutator $response_mutator an object to mutate the response based on the results of the cache check. Defaults to nothing + * @var CacheListener[] $cache_listeners an array of objects to act on the response based on the results of the cache check. + Defaults to an empty array * } */ public function __construct(CacheItemPoolInterface $pool, StreamFactory $streamFactory, array $config = []) @@ -132,7 +133,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl // if the request not is cachable, move to $next if (!in_array($method, $this->config['methods'])) { return $next($request)->then(function (ResponseInterface $response) use ($request) { - $response = $this->handleResponseMutator($request, $response, false, null); + $response = $this->handleCacheListeners($request, $response, false, null); return $response; }); @@ -148,7 +149,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl if (array_key_exists('expiresAt', $data) && (null === $data['expiresAt'] || time() < $data['expiresAt'])) { // This item is still valid according to previous cache headers $response = $this->createResponseFromCacheItem($cacheItem); - $response = $this->handleResponseMutator($request, $response, true, $cacheItem); + $response = $this->handleCacheListeners($request, $response, true, $cacheItem); return new FulfilledPromise($response); } @@ -170,7 +171,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl * We do not have the item in cache. This plugin did not add If-Modified-Since * or If-None-Match headers. Return the response from server. */ - return $this->handleResponseMutator($request, $response, false, $cacheItem); + return $this->handleCacheListeners($request, $response, false, $cacheItem); } // The cached response we have is still valid @@ -180,7 +181,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl $cacheItem->set($data)->expiresAfter($this->calculateCacheItemExpiresAfter($maxAge)); $this->pool->save($cacheItem); - return $this->handleResponseMutator($request, $this->createResponseFromCacheItem($cacheItem), true, $cacheItem); + return $this->handleCacheListeners($request, $this->createResponseFromCacheItem($cacheItem), true, $cacheItem); } if ($this->isCacheable($response)) { @@ -205,7 +206,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl $this->pool->save($cacheItem); } - return $this->handleResponseMutator($request, $response, false, null); + return $this->handleCacheListeners($request, $response, false, isset($cacheItem) ? $cacheItem : null); }); } @@ -352,7 +353,7 @@ private function configureOptions(OptionsResolver $resolver) 'methods' => ['GET', 'HEAD'], 'respect_response_cache_directives' => ['no-cache', 'private', 'max-age', 'no-store'], 'cache_key_generator' => null, - 'response_mutator' => null, + 'cache_listeners' => [], ]); $resolver->setAllowedTypes('cache_lifetime', ['int', 'null']); @@ -367,7 +368,7 @@ private function configureOptions(OptionsResolver $resolver) return empty($matches); }); - $resolver->setAllowedTypes('response_mutator', ['null', 'Http\Client\Common\Plugin\Cache\Mutator\ResponseMutator']); + $resolver->setAllowedTypes('cache_listeners', ['array']); $resolver->setNormalizer('respect_cache_headers', function (Options $options, $value) { if (null !== $value) { @@ -454,7 +455,7 @@ private function getETag(CacheItemInterface $cacheItem) } /** - * Call the reponse mutator, if one is set. + * Call the cache listeners, if they are set. * * @param RequestInterface $request * @param ResponseInterface $response @@ -463,10 +464,10 @@ private function getETag(CacheItemInterface $cacheItem) * * @return ResponseInterface */ - private function handleResponseMutator(RequestInterface $request, ResponseInterface $response, $cacheHit, CacheItemInterface $cacheItem) + private function handleCacheListeners(RequestInterface $request, ResponseInterface $response, $cacheHit, CacheItemInterface $cacheItem) { - if (null !== $this->config['response_mutator']) { - $response = $this->config['response_mutator']->mutate($request, $response, $cacheHit, $cacheItem); + foreach ( $this->config['cache_listeners'] as $cacheListener ) { + $response = $cacheListener->onCacheResponse($request, $response, $cacheHit, $cacheItem); } return $response; From 3edb6dfe0268a4d8b699db185a48ccea5dd23264 Mon Sep 17 00:00:00 2001 From: iconnor Date: Tue, 16 Jan 2018 09:26:36 -0600 Subject: [PATCH 12/17] Respecting code style. --- src/CachePlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CachePlugin.php b/src/CachePlugin.php index 4f541be..36a9aeb 100644 --- a/src/CachePlugin.php +++ b/src/CachePlugin.php @@ -466,7 +466,7 @@ private function getETag(CacheItemInterface $cacheItem) */ private function handleCacheListeners(RequestInterface $request, ResponseInterface $response, $cacheHit, CacheItemInterface $cacheItem) { - foreach ( $this->config['cache_listeners'] as $cacheListener ) { + foreach ($this->config['cache_listeners'] as $cacheListener) { $response = $cacheListener->onCacheResponse($request, $response, $cacheHit, $cacheItem); } From ce5224db398b90bbc9a9877c0dc4fa4f9c3c193e Mon Sep 17 00:00:00 2001 From: iconnor Date: Tue, 16 Jan 2018 09:27:31 -0600 Subject: [PATCH 13/17] bad docblock --- src/CachePlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CachePlugin.php b/src/CachePlugin.php index 36a9aeb..dde11f5 100644 --- a/src/CachePlugin.php +++ b/src/CachePlugin.php @@ -61,7 +61,7 @@ final class CachePlugin implements Plugin * @var array $respect_response_cache_directives list of cache directives this plugin will respect while caching responses * @var CacheKeyGenerator $cache_key_generator an object to generate the cache key. Defaults to a new instance of SimpleGenerator * @var CacheListener[] $cache_listeners an array of objects to act on the response based on the results of the cache check. - Defaults to an empty array + * Defaults to an empty array * } */ public function __construct(CacheItemPoolInterface $pool, StreamFactory $streamFactory, array $config = []) From 27e053b0bdb3e8af617ad69f876d9aa6b363376c Mon Sep 17 00:00:00 2001 From: iconnor Date: Tue, 16 Jan 2018 09:55:44 -0600 Subject: [PATCH 14/17] Must be nullable. --- src/Cache/Listener/AddHeaderCacheListener.php | 2 +- src/Cache/Listener/CacheListener.php | 2 +- src/CachePlugin.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Cache/Listener/AddHeaderCacheListener.php b/src/Cache/Listener/AddHeaderCacheListener.php index 91907d0..077393e 100644 --- a/src/Cache/Listener/AddHeaderCacheListener.php +++ b/src/Cache/Listener/AddHeaderCacheListener.php @@ -35,7 +35,7 @@ public function __construct($headerName = 'X-Cache') * * @return string */ - public function onCacheResponse(RequestInterface $request, ResponseInterface $response, $fromCache, CacheItemInterface $cacheItem) + public function onCacheResponse(RequestInterface $request, ResponseInterface $response, $fromCache, $cacheItem) { return $response->withHeader($this->headerName, $cacheHit ? 'HIT' : 'MISS'); } diff --git a/src/Cache/Listener/CacheListener.php b/src/Cache/Listener/CacheListener.php index aeb0a8d..3d3a787 100644 --- a/src/Cache/Listener/CacheListener.php +++ b/src/Cache/Listener/CacheListener.php @@ -26,5 +26,5 @@ interface CacheListener * * @return string */ - public function onCacheResponse(RequestInterface $request, ResponseInterface $response, $fromCache, CacheItemInterface $cacheItem); + public function onCacheResponse(RequestInterface $request, ResponseInterface $response, $fromCache, $cacheItem); } diff --git a/src/CachePlugin.php b/src/CachePlugin.php index dde11f5..8225b75 100644 --- a/src/CachePlugin.php +++ b/src/CachePlugin.php @@ -464,7 +464,7 @@ private function getETag(CacheItemInterface $cacheItem) * * @return ResponseInterface */ - private function handleCacheListeners(RequestInterface $request, ResponseInterface $response, $cacheHit, CacheItemInterface $cacheItem) + private function handleCacheListeners(RequestInterface $request, ResponseInterface $response, $cacheHit, $cacheItem) { foreach ($this->config['cache_listeners'] as $cacheListener) { $response = $cacheListener->onCacheResponse($request, $response, $cacheHit, $cacheItem); From c5e2ac2f3e5b68d5d4f2d03d6e6b4d2e285baa5b Mon Sep 17 00:00:00 2001 From: iconnor Date: Tue, 16 Jan 2018 09:58:12 -0600 Subject: [PATCH 15/17] Bad return type. --- src/Cache/Listener/AddHeaderCacheListener.php | 2 +- src/Cache/Listener/CacheListener.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Cache/Listener/AddHeaderCacheListener.php b/src/Cache/Listener/AddHeaderCacheListener.php index 077393e..12e91f0 100644 --- a/src/Cache/Listener/AddHeaderCacheListener.php +++ b/src/Cache/Listener/AddHeaderCacheListener.php @@ -33,7 +33,7 @@ public function __construct($headerName = 'X-Cache') * Note that checking `$cacheItem->isHit()` is not sufficent to determine this. * @param CacheItemInterface|null $cacheItem * - * @return string + * @return ResponseInterface */ public function onCacheResponse(RequestInterface $request, ResponseInterface $response, $fromCache, $cacheItem) { diff --git a/src/Cache/Listener/CacheListener.php b/src/Cache/Listener/CacheListener.php index 3d3a787..3bf6007 100644 --- a/src/Cache/Listener/CacheListener.php +++ b/src/Cache/Listener/CacheListener.php @@ -24,7 +24,7 @@ interface CacheListener * Note that checking `$cacheItem->isHit()` is not sufficent to determine this. * @param CacheItemInterface|null $cacheItem * - * @return string + * @return ResponseInterface */ public function onCacheResponse(RequestInterface $request, ResponseInterface $response, $fromCache, $cacheItem); } From d0f2494b977069fcea07e0a0092e060d885ac3ac Mon Sep 17 00:00:00 2001 From: iconnor Date: Tue, 16 Jan 2018 10:04:20 -0600 Subject: [PATCH 16/17] Wrong var name. --- src/Cache/Listener/AddHeaderCacheListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cache/Listener/AddHeaderCacheListener.php b/src/Cache/Listener/AddHeaderCacheListener.php index 12e91f0..ed306e3 100644 --- a/src/Cache/Listener/AddHeaderCacheListener.php +++ b/src/Cache/Listener/AddHeaderCacheListener.php @@ -37,6 +37,6 @@ public function __construct($headerName = 'X-Cache') */ public function onCacheResponse(RequestInterface $request, ResponseInterface $response, $fromCache, $cacheItem) { - return $response->withHeader($this->headerName, $cacheHit ? 'HIT' : 'MISS'); + return $response->withHeader($this->headerName, $fromCache ? 'HIT' : 'MISS'); } } From 699d45e5232d91d07b33a9ad405a4014fbe0242e Mon Sep 17 00:00:00 2001 From: iconnor Date: Mon, 29 Jan 2018 09:33:30 -0600 Subject: [PATCH 17/17] Adding changelog and updating version in composer. --- CHANGELOG.md | 6 ++++++ composer.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 795a3ff..e822f6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 1.6.0 - 2017-01-29 + +### Added + +* Added `cache_listeners` option, which takes an array of `CacheListener`s, who get notified and can optionally act on a Response based on a cache hit or miss event. An implementation, `AddHeaderCacheListener`, is provided which will add an `X-Cache` header to the response with this information. + ## 1.5.0 - 2017-11-29 ### Added diff --git a/composer.json b/composer.json index 3ce18be..d875cdb 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.5-dev" + "dev-master": "1.6-dev" } } }