UPDATE 25/03/2019 The gist below has been refactored and is available as a package. It's now easier to re-configure the cache for every request made by the same Guzzle client! Check the readme of the repository on Github or fetch the package with
composer require brightfish/caching-guzzle
. (It still works with Laravel 5.8 ;)
While working on a Laravel project in which repeated HTTP requests are made against several APIs, I needed a simple and unobtrusive way to cache the API responses for a time to live (TTL) specific to each API.
The project in question uses an interface around Guzzle's ClientInterface
where each
implementation of it corresponds to one of the services the project is talking to.
That way I could manage all the requests in a likely fashion, while taking care of the
requirements of each API. One those was the requirement to have the ability to enable and configure the caching of responses
differently for each service. Because each service instantiates a Guzzle object, I was able to instantiate the below
GuzzleResponseCache
class
with a specific TTL for each of them.
The GuzzleResponseCache
class is a Guzzle middleware,
which means that it handles the execution of an intermediary handler function,
i.e. a function that can intercept and modify the requests performed by Guzzle as well as the returned responses.
The handler functions are added to a stack and upon each Guzzle request the stack will be traversed and every handler will be called one by one.
Here is how the GuzzleResponseCache
middleware is added to a Guzzle instance:
$guzzleHandlerStack = \GuzzleHttp\HandlerStack:create();
$cache = \Illuminate\Support\Facades\Cache::store('database');
$guzzleHandlerStack->push(new GuzzleResponseCache($cache, 86400));
$client = new \GuzzleHttp\Client([
handler => $guzzleHandlerStack
]);
This will cache all requests done with $client
for 24 hours in the database — making use
of Laravel's Cache
facade (provided you have migrated a cache table with artisan).