Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Guzzle Cache Middleware Laravel Package

kevinrob/guzzle-cache-middleware

RFC 7234-compliant HTTP cache middleware for Guzzle 6+. Add to a HandlerStack to transparently cache responses and speed up API calls. Supports PSR-7 and multiple backends: Laravel Cache, Flysystem, PSR-6/16, and WordPress object cache.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Middleware-Based Design: The package leverages Guzzle’s HandlerStack middleware pattern, making it a natural fit for Laravel applications that already use Guzzle (e.g., for API calls, HTTP clients, or external service integrations). It integrates seamlessly without requiring architectural overhauls.
  • PSR Compliance: Supports PSR-7 (HTTP messages), PSR-6 (caching), and PSR-16 (simple caching), ensuring compatibility with Laravel’s ecosystem (e.g., Illuminate\Cache, League\Flysystem).
  • Strategy Pattern: Offers modular caching strategies (private, public, greedy, delegating), allowing fine-grained control over caching behavior per use case (e.g., API responses vs. authenticated requests).
  • RFC 7234 Compliance: Adheres to HTTP caching standards, ensuring correctness in shared/public caching scenarios.

Integration Feasibility

  • Laravel Native Support: Direct integration with Laravel’s cache drivers (Redis, Memcached, database, etc.) via LaravelCacheStorage. No additional infrastructure needed for most use cases.
  • Minimal Boilerplate: Requires only 3–5 lines of code to implement basic caching (e.g., adding middleware to HandlerStack). Advanced configurations (e.g., delegating strategies) add complexity but remain optional.
  • Guzzle Integration: Works with Guzzle 6+, which Laravel often uses for HTTP clients (e.g., HttpClient facade). No version conflicts with Laravel’s default Guzzle version.
  • Binary Data Handling: Fixed issues with truncated binary responses (v7.0.0), critical for APIs returning files (e.g., images, PDFs).

Technical Risk

  • Cache Invalidation Complexity: Misconfiguring strategies (e.g., PublicCacheStrategy for authenticated endpoints) could lead to stale data or security leaks. Requires careful validation of Vary/Authorization headers.
  • Storage Backend Dependencies: Performance/scalability hinges on the underlying cache driver (e.g., Redis vs. file system). Poorly chosen storage (e.g., local filesystem for high traffic) could become a bottleneck.
  • Greedy Caching Pitfalls: Overriding server-provided Cache-Control headers (via GreedyCacheStrategy) may violate API contracts. Should be used only for unreliable APIs.
  • Laravel-Specific Quirks:
    • Cache Tagging: Laravel’s cache tagging system isn’t directly supported; manual invalidation may be needed for tagged caches.
    • Queue Jobs: Cached responses in queued jobs might not reflect real-time changes (e.g., if the job runs after the cache expires but before the next request).

Key Questions for TPM

  1. Use Case Prioritization:
    • Are we caching public APIs (shared cache), user-specific data (private cache), or both?
    • Are there APIs with no caching headers (requiring GreedyCacheStrategy)?
  2. Performance vs. Freshness Tradeoff:
    • What’s the acceptable stale-while-revalidate window for critical endpoints?
    • Should we use delegating strategies to route requests dynamically (e.g., by domain)?
  3. Storage Backend:
    • Which Laravel cache driver (Redis, database, etc.) will we use, and how will we handle cache misses under load?
    • For high-throughput systems, is PSR-6 (e.g., Predis) better than Laravel’s native cache?
  4. Monitoring and Debugging:
    • How will we log cache hits/misses and detect stale data in production?
    • Are there tools (e.g., Laravel Telescope) to monitor cache performance?
  5. Fallback Mechanisms:
    • What’s the plan if the cache backend fails (e.g., Redis downtime)? Should we implement a fallback to no caching?
  6. Testing Strategy:
    • How will we test cache invalidation (e.g., after data updates)?
    • Should we mock the cache layer in unit tests or use a real in-memory store (e.g., ArrayCachePool)?

Integration Approach

Stack Fit

  • Laravel Ecosystem:
    • Guzzle Integration: Works natively with Laravel’s HttpClient facade or custom Guzzle instances.
    • Cache Drivers: Leverages Laravel’s built-in cache (Redis, Memcached, database, file) via LaravelCacheStorage.
    • Service Container: Can be bound as a singleton in Laravel’s container for reuse across requests.
  • Microservices/APIs:
    • Ideal for external API clients (e.g., payment gateways, third-party services) where reducing latency is critical.
    • Useful for background jobs (e.g., shouldQueue) that fetch external data.
  • Legacy Systems:
    • Can wrap existing Guzzle clients (e.g., in legacy monoliths) without refactoring.

Migration Path

  1. Pilot Phase:
    • Start with non-critical endpoints (e.g., public APIs with stable responses).
    • Use PrivateCacheStrategy + Laravel Redis for low-risk testing.
  2. Incremental Rollout:
    • Phase 1: Add caching to read-heavy, low-churn APIs (e.g., product catalogs).
    • Phase 2: Extend to authenticated endpoints (using PrivateCacheStrategy with Authorization headers excluded from cache keys).
    • Phase 3: Implement delegating strategies for dynamic routing (e.g., different TTLs per API domain).
  3. Fallback Strategy:
    • Use NullCacheStrategy as a default, with feature flags to toggle caching per client.

Compatibility

  • Laravel Versions:
    • Supports Laravel 10+ (tested up to v13 in v8.0.0-RC1). For older versions, use v7.x.
    • PHP 8.2+ required (v8.0.0+). PHP 8.1+ for v7.x.
  • Guzzle Versions:
    • Compatible with Guzzle 6.5+ (Laravel’s default). Guzzle 7+ support added in v3.4.0.
  • Cache Backends:
    • Tested: Redis, Memcached, database, file system (Flysystem), PSR-6/16.
    • Untested: Custom cache drivers may need adapter wrappers.

Sequencing

  1. Setup:
    • Install via Composer: composer require kevinrob/guzzle-cache-middleware.
    • Bind the middleware to Laravel’s container (optional but recommended for reuse):
      $app->singleton(CacheMiddleware::class, fn() => new CacheMiddleware(
          new PrivateCacheStrategy(new LaravelCacheStorage(Cache::store('redis')))
      ));
      
  2. Basic Integration:
    • Add middleware to HandlerStack in a service or facade:
      use GuzzleHttp\HandlerStack;
      use Kevinrob\GuzzleCache\CacheMiddleware;
      
      $stack = HandlerStack::create();
      $stack->push(app(CacheMiddleware::class), 'cache');
      $client = new Client(['handler' => $stack]);
      
  3. Advanced Configurations:
    • Delegating Strategies: Implement RequestMatcherInterface for dynamic routing.
    • Greedy Caching: Use for APIs with missing Cache-Control headers.
    • Public Caching: For shared resources (e.g., CDN-backed APIs).
  4. Validation:
    • Test cache hits/misses with tools like Postman or Laravel Dusk.
    • Verify Vary/Authorization headers are handled correctly.

Operational Impact

Maintenance

  • Dependency Updates:
    • Monitor for Guzzle/PHP version drops (e.g., PHP 8.2+ required for v8.0.0).
    • Laravel cache driver updates may require middleware version bumps.
  • Cache Schema:
    • No database migrations needed, but manual cache invalidation may be required for tagged caches.
  • Logging:
    • Add middleware to log cache events (e.g., hits/misses, TTLs):
      $middleware = new CacheMiddleware($strategy);
      $middleware->onCacheHit(fn($request, $response) => Log::debug('Cache hit', ['url' => $request->getUri()]));
      

Support

  • Debugging:
    • Cache Corruption: Use CacheMiddleware::inspectAll() to debug entries.
    • Stale Data: Implement cache busting (e.g., versioned keys) for critical data.
  • Performance Tuning:
    • Monitor cache hit ratios (e.g., via Prometheus or custom metrics).
    • Adjust TTLs based on data volatility (e.g., 5s for stock prices, 1h for product catalogs).
  • Common Issues:
    • Binary Data: Ensure stream_get_contents() is used for large responses (fixed in v7.0.0).
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport