Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple Laravel 5.5 + Guzzle 6 cache middleware
<?php namespace App\Clients\Middleware;
use GuzzleHttp\Psr7\Response;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Promise\PromiseInterface;
use GuzzleHttp\Promise\FulfilledPromise;
use Illuminate\Contracts\Cache\Repository;
/**
* Cache HTTP responses
*
* @version 0.0.1
* @author dotburo <hello@dotburo.org>
*/
class GuzzleResponseCache
{
/**
* Cache time to live
*
* @var int
*/
private $ttl = 7 * 24 * 60; // one week
/**
* A laravel cache driver instance
*
* @var Repository
*/
private $cache;
/**
* Cache the laravel cache driver instance
*
* @param Repository $cache
* @param null $ttl
*/
public function __construct(Repository $cache, $ttl = null)
{
$this->cache = $cache;
$this->ttl = $ttl ?? $this->ttl;
}
/**
* The middleware handler
*
* @param callable $handler
* @return callable
*/
public function __invoke(callable $handler): callable
{
return function (RequestInterface $request, array $options) use (&$handler) {
# both path and query string are needed to build unique cache keys,
# eg. a REST URL doesn't necessarily contain a query string
$path = $request->getUri()->getPath();
$query = $request->getUri()->getQuery();
$key = "$path?$query";
# get from cache
$entry = $this->get($key);
if ($entry) {
if (app()->environment() !== 'production') {
$this->log($key);
}
return new FulfilledPromise(
new Response(200, [], $entry)
);
}
/** @var PromiseInterface $promise */
$promise = $handler($request, $options);
return $promise->then(
function (ResponseInterface $response) use ($options, $key) {
# save to cache
$this->save($key, (string)$response->getBody());
return $response;
}
);
};
}
/**
* Try getting cached data from cache
*
* @param string $key
* @return mixed|null
*/
private function get(string $key)
{
try {
return $this->cache->get($key);
} catch (\Exception $ignore) {
return null;
}
}
/**
* Persist the data to cache
*
* @param string $key
* @param string $data
* @return bool
*/
private function save(string $key, string $data): bool
{
try {
return $this->cache->add($key, $data, $this->ttl);
} catch (\Exception $ignore) {
return false;
}
}
/**
* Dump cache key to log file
*
* @param string $msg
* @return void
*/
private function log(string $msg): void
{
logger('Retrieved from cache: ' . $msg);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment