From a4f5158a67951d00af30f11933cf0a7a26e2de68 Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Tue, 9 Apr 2024 10:38:26 +0200 Subject: [PATCH] Add caching to UrlKeySetFactory Implemented caching in the UrlKeySetFactory to store and retrieve URL data. This is accomplished by adding the PSR Cache package to the composer.json file and incorporating it with the CacheItemPoolInterface in the UrlKeySetFactory class. This addition intends to improve performance by storing data from previous URL requests and reusing them, if available, instead of making repeated URL requests. --- composer.json | 1 + phpstan-baseline.neon | 5 +++ .../KeyManagement/UrlKeySetFactory.php | 31 +++++++++++++++++-- src/Library/composer.json | 1 + 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 8a178bd9..76a5f595 100644 --- a/composer.json +++ b/composer.json @@ -55,6 +55,7 @@ "brick/math": "^0.9|^0.10|^0.11|^0.12", "paragonie/constant_time_encoding": "^2.6", "paragonie/sodium_compat": "^1.20", + "psr/cache": "^3.0", "psr/clock": "^1.0", "psr/event-dispatcher": "^1.0", "psr/http-client": "^1.0", diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index a5104296..adbac08c 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -2043,6 +2043,11 @@ parameters: count: 1 path: src/Library/KeyManagement/KeyConverter/RSAKey.php + - + message: "#^Method Jose\\\\Component\\\\KeyManagement\\\\UrlKeySetFactory\\:\\:getContent\\(\\) should return string but returns mixed\\.$#" + count: 1 + path: src/Library/KeyManagement/UrlKeySetFactory.php + - message: "#^Cannot cast mixed to string\\.$#" count: 1 diff --git a/src/Library/KeyManagement/UrlKeySetFactory.php b/src/Library/KeyManagement/UrlKeySetFactory.php index 6bd2553c..ede4d62d 100644 --- a/src/Library/KeyManagement/UrlKeySetFactory.php +++ b/src/Library/KeyManagement/UrlKeySetFactory.php @@ -4,9 +4,11 @@ namespace Jose\Component\KeyManagement; +use Psr\Cache\CacheItemPoolInterface; use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestFactoryInterface; use RuntimeException; +use Symfony\Component\Cache\Adapter\NullAdapter; use Symfony\Contracts\HttpClient\HttpClientInterface; use function assert; @@ -15,6 +17,10 @@ */ abstract class UrlKeySetFactory { + private CacheItemPoolInterface $cacheItemPool; + + private int $expiresAfter = 3600; + public function __construct( private readonly ClientInterface|HttpClientInterface $client, private readonly null|RequestFactoryInterface $requestFactory = null @@ -35,6 +41,13 @@ public function __construct( ClientInterface::class )); } + $this->cacheItemPool = new NullAdapter(); + } + + public function enabledCache(CacheItemPoolInterface $cacheItemPool, int $expiresAfter = 3600): void + { + $this->cacheItemPool = $cacheItemPool; + $this->expiresAfter = $expiresAfter; } /** @@ -42,10 +55,22 @@ public function __construct( */ protected function getContent(string $url, array $header = []): string { - if ($this->client instanceof HttpClientInterface) { - return $this->sendSymfonyRequest($url, $header); + $cacheKey = hash('xxh128', $url); + $item = $this->cacheItemPool->getItem($cacheKey); + if ($item->isHit()) { + return $item->get(); } - return $this->sendPsrRequest($url, $header); + + $content = $this->client instanceof HttpClientInterface ? $this->sendSymfonyRequest( + $url, + $header + ) : $this->sendPsrRequest($url, $header); + $item = $this->cacheItemPool->getItem($cacheKey); + $item->expiresAfter($this->expiresAfter); + $item->set($content); + $this->cacheItemPool->save($item); + + return $content; } /** diff --git a/src/Library/composer.json b/src/Library/composer.json index 0f717183..271a683f 100644 --- a/src/Library/composer.json +++ b/src/Library/composer.json @@ -44,6 +44,7 @@ "brick/math": "^0.9|^0.10|^0.11|^0.12", "paragonie/constant_time_encoding": "^2.6", "paragonie/sodium_compat": "^1.20", + "psr/cache": "^3.0", "psr/clock": "^1.0", "psr/http-factory": "^1.0", "psr/http-client": "^1.0",