kevinrob/guzzle-cache-middleware
RFC 7234–compliant HTTP cache middleware for Guzzle 6+ using a HandlerStack. Improve API call performance with transparent caching. Supports PSR-7 and multiple storages: Laravel cache, Flysystem, PSR-6/16, and WordPress object cache.
Cache facade, Psr\Cache interfaces), reducing integration friction.HandlerStack, enabling non-intrusive caching without modifying core HTTP logic.Cache facade (Redis, Memcached, database, etc.) via LaravelCacheStorage.Storage::disk()) or third-party cache adapters (e.g., cache/simple-cache-bridge).HttpClient (Guzzle 7+) is backward-compatible, though minor adjustments may be needed for Guzzle 7+ features (e.g., sink option handling).AppServiceProvider or as a dedicated CacheServiceProvider for centralized configuration.| Risk Area | Mitigation Strategy |
|---|---|
| Cache Invalidation | Use CacheMiddleware::delete() or leverage Laravel’s cache tags for bulk invalidation. |
| Binary Data Corruption | Fixed in v7.0.0; ensure package is ≥v7.0.0. |
| TTL Misconfiguration | Defaults to RFC 7234; override via GreedyCacheStrategy or Cache-Control headers. |
| Thread Safety | PSR-6/PSR-16 storage backends (e.g., Redis) are thread-safe; avoid shared-memory issues. |
| Guzzle 7+ Breaking Changes | Test sink option handling (fixed in v8.0.0-RC1) and stream rewinding. |
| DST/Timezone Bugs | Fixed in v8.0.0-RC1; use PSR-20 Clock for deterministic time management. |
twitter.com)?DelegatingCacheStrategy with custom RequestMatcher interfaces.max-age and s-maxage headers.Vary headers (e.g., Accept-Encoding, User-Agent)?Vary headers by default.events system.HttpClient (v1.0+) is compatible; wrap it with CacheMiddleware.Psr\Cache interfaces for portability.WordPressObjectCacheStorage.TwitterClient).PrivateCacheStrategy + Redis.DelegatingCacheStrategy to exclude sensitive endpoints (e.g., auth tokens).$strategy = new DelegatingCacheStrategy(new NullCacheStrategy());
$strategy->registerRequestMatcher(
new AuthEndpointMatcher(),
new NullCacheStrategy() // Bypass cache for auth endpoints
);
HttpClient instances with cached versions.Cache facade as the default storage.Monolog channel) to track cache metrics.| Component | Compatibility Notes |
|---|---|
| Laravel 10+ | Fully supported (tested up to v8.0.0-RC1). |
| Guzzle 7+ | Minor adjustments needed for sink option (fixed in v8.0.0-RC1). |
| Redis/Predis | PSR-6 adapter (cache/redis-adapter) recommended. |
| Database Cache | Use database driver with Psr6CacheStorage. |
| Filesystem Cache | Works with Storage::disk('cache') via FlysystemStorage. |
| WordPress | Native support via WordPressObjectCacheStorage. |
.env:
CACHE_DRIVER=redis
AppServiceProvider:
public function boot()
{
$stack = HandlerStack::create();
$stack->push(
new CacheMiddleware(
new PrivateCacheStrategy(
new LaravelCacheStorage(Cache::store())
)
),
'cache'
);
$this->app->singleton(GuzzleHttp\Client::class, fn() => new Client(['handler' => $stack]));
}
DelegatingCacheStrategy for endpoints requiring no caching.max-age headers or use GreedyCacheStrategy for static APIs.CacheMiddleware::delete() in event listeners (e.g., CacheTaggedEvent).sink option).$stack->push(
TapMiddleware::tap(fn(Transfer $transfer) => logger()->debug(
'Cache hit/miss', ['request' => $transfer->getRequest()->getUri()]
)),
'logging'
);
CacheMiddleware::delete() or Cache::forget().Cache-Control headers or use GreedyCacheStrategy.CACHING.md in Laravel’s docs with:
Laravel Redis tools.Cache::rememberForever() sparingly for large responses.| Failure Scenario | Impact | Mitigation Strategy |
|---|---|---|
| Cache Backend Down | Cache misses → increased latency | Fallback to NullCacheStrategy or disable caching gracefully. |
| **Corrupted |
How can I help you explore Laravel packages today?