skip to Main Content

I’m playing around with the GuzzleHttp client, GuzzleCacheMiddleware and Memcached.

The setup is calling the same url with different parameters.

This results in one! memcached hit, so I think the memcached key is created from the url and only the url.

Can I somehow change this behaviour, so the key includes a md5 of the parameters?

2

Answers


  1. You would have to create your own CacheStrategy class. For example you can extend PrivateCacheStrategy class and override getCacheKey method which is responsible for creating the cache key.

    https://github.com/Kevinrob/guzzle-cache-middleware/blob/master/src/Strategy/PrivateCacheStrategy.php#L123

    You are right that it creates storage key based on only the URL and request method.

    Login or Signup to reply.
  2. Decided to look into it. You are right that it needs GreedyCacheStrategy because it literally caches everything regardless of any RFC standards.

    Custom class for cache key creating.

    class ParamsGreedyCacheStrategy extends GreedyCacheStrategy
    {
        /**
         * Ignoring any headers, just straight up cache key based on method, URI, request body/params
         *
         * @param RequestInterface $request
         * @param KeyValueHttpHeader|null $varyHeaders
         * @return string
         */
        protected function getCacheKey(RequestInterface $request, KeyValueHttpHeader $varyHeaders = null)
        {
            return hash(
                'sha256',
                'greedy' . $request->getMethod() . $request->getUri() . $request->getBody()
            );
        }
    }
    

    Creating requests. I used Laravel caching here, you can use memcached. I also allow POST HTTP method to be cached, because by default only GET is being cached!

    $handlerStack = HandlerStack::create();
    
    $cacheMiddleware = new CacheMiddleware(
        new ParamsGreedyCacheStrategy(
            new LaravelCacheStorage(
                Cache::store('file')
            ),
            10
        )
    );
    
    // Not documented, but if you look at the source code they have methods for setting allowed HTTP methods. By default, only GET is allowed (per standards).
    $cacheMiddleware->setHttpMethods(['GET' => true, 'POST' => true]);
    
    $handlerStack->push(
        $cacheMiddleware,
        'cache'
    );
    
    $client = new Client([
        'base_uri' => 'https://example.org',
        'http_errors' => false,
        'handler' => $handlerStack
    ]);
    
    
    for($i = 0; $i < 4; $i++) {
        $response = $client->post('/test', [
            'form_params' => ['val' => $i]
        ]);
        // Middleware attaches 'X-Kevinrob-Cache' header that let's us know if we hit the cache or not!
        dump($response->getHeader('X-Kevinrob-Cache'));
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search