kevinrob/guzzle-cache-middleware

为 Guzzle 6 提供的 HTTP/1.1 缓存。这是一个简单的 Middleware,可以添加到 HandlerStack 中。(RFC 7234)

v5.1.0 2023-11-09 06:53 UTC

README

Latest Stable Version Total Downloads License Tests Scrutinizer Code Quality Code Coverage

Guzzle 6+ 提供的 HTTP 缓存。这是一个简单的 Middleware,可以添加到 HandlerStack 中。

目标

  • RFC 7234 兼容性
  • 性能和透明度
  • 确保与 PSR-7 兼容

内置存储接口

安装

composer require kevinrob/guzzle-cache-middleware

或者在 composer.json 中添加它,然后运行 composer update kevinrob/guzzle-cache-middleware

为什么?

性能。通常需要执行一些 HTTP 调用来渲染页面,这需要花费时间。

如何?

通过在 Guzzle 的 HandlerStack 顶部添加一个简单的 Middleware。

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use Kevinrob\GuzzleCache\CacheMiddleware;

// Create default HandlerStack
$stack = HandlerStack::create();

// Add this middleware to the top with `push`
$stack->push(new CacheMiddleware(), 'cache');

// Initialize the client with the handler option
$client = new Client(['handler' => $stack]);

示例

Doctrine/Cache

您可以使用 Doctrine/Cache 中的缓存

[...]
use Doctrine\Common\Cache\FilesystemCache;
use Kevinrob\GuzzleCache\Strategy\PrivateCacheStrategy;
use Kevinrob\GuzzleCache\Storage\DoctrineCacheStorage;

[...]
$stack->push(
  new CacheMiddleware(
    new PrivateCacheStrategy(
      new DoctrineCacheStorage(
        new FilesystemCache('/tmp/')
      )
    )
  ),
  'cache'
);

您可以使用 ChainCache 来使用多个 CacheProvider 实例。使用此提供程序时,您必须按照从快到慢的顺序排序不同的缓存。这样,您就可以拥有一个非常快的缓存。

[...]
use Doctrine\Common\Cache\ChainCache;
use Doctrine\Common\Cache\ArrayCache;
use Doctrine\Common\Cache\FilesystemCache;
use Kevinrob\GuzzleCache\Strategy\PrivateCacheStrategy;
use Kevinrob\GuzzleCache\Storage\DoctrineCacheStorage;

[...]
$stack->push(new CacheMiddleware(
  new PrivateCacheStrategy(
    new DoctrineCacheStorage(
      new ChainCache([
        new ArrayCache(),
        new FilesystemCache('/tmp/'),
      ])
    )
  )
), 'cache');

Laravel 缓存

您可以使用 Laravel 中的缓存,例如 Redis、Memcache 等。

[...]
use Illuminate\Support\Facades\Cache;
use Kevinrob\GuzzleCache\Strategy\PrivateCacheStrategy;
use Kevinrob\GuzzleCache\Storage\LaravelCacheStorage;

[...]

$stack->push(
  new CacheMiddleware(
    new PrivateCacheStrategy(
      new LaravelCacheStorage(
        Cache::store('redis')
      )
    )
  ),
  'cache'
);

Flysystem

[...]
use League\Flysystem\Adapter\Local;
use Kevinrob\GuzzleCache\Strategy\PrivateCacheStrategy;
use Kevinrob\GuzzleCache\Storage\FlysystemStorage;

[...]

$stack->push(
  new CacheMiddleware(
    new PrivateCacheStrategy(
      new FlysystemStorage(
        new Local('/path/to/cache')
      )
    )
  ),
  'cache'
);

WordPress 对象缓存

[...]
use Kevinrob\GuzzleCache\Strategy\PrivateCacheStrategy;
use Kevinrob\GuzzleCache\Storage\WordPressObjectCacheStorage;

[...]

$stack->push(
  new CacheMiddleware(
    new PrivateCacheStrategy(
      new WordPressObjectCacheStorage()
    )
  ),
  'cache'
);

公共和共享

可以将公共共享缓存添加到堆栈中

[...]
use Doctrine\Common\Cache\FilesystemCache;
use Doctrine\Common\Cache\PredisCache;
use Kevinrob\GuzzleCache\Strategy\PrivateCacheStrategy;
use Kevinrob\GuzzleCache\Strategy\PublicCacheStrategy;
use Kevinrob\GuzzleCache\Storage\DoctrineCacheStorage;

[...]
// Private caching
$stack->push(
  new CacheMiddleware(
    new PrivateCacheStrategy(
      new DoctrineCacheStorage(
        new FilesystemCache('/tmp/')
      )
    )
  ),
  'private-cache'
);

// Public caching
$stack->push(
  new CacheMiddleware(
    new PublicCacheStrategy(
      new DoctrineCacheStorage(
        new PredisCache(
          new Predis\Client('tcp://10.0.0.1:6379')
        )
      )
    )
  ),
  'shared-cache'
);

贪婪缓存

在某些情况下,服务器可能发送不足或不发送任何缓存头。使用贪婪缓存策略允许您定义自己的过期 TTL,同时忽略任何可能存在的缓存头

[...]
use Kevinrob\GuzzleCache\KeyValueHttpHeader;
use Kevinrob\GuzzleCache\Strategy\GreedyCacheStrategy;
use Kevinrob\GuzzleCache\Storage\DoctrineCacheStorage;
use Doctrine\Common\Cache\FilesystemCache;

[...]
// Greedy caching
$stack->push(
  new CacheMiddleware(
    new GreedyCacheStrategy(
      new DoctrineCacheStorage(
        new FilesystemCache('/tmp/')
      ),
      1800, // the TTL in seconds
      new KeyValueHttpHeader(['Authorization']) // Optional - specify the headers that can change the cache key
    )
  ),
  'greedy-cache'
);

委托缓存

因为您的客户端可能调用不同的应用程序,在不同的域名上,您可能需要定义适合您的请求的策略。

为了解决这个问题,您只需要定义一个默认的缓存策略,并通过实现自己的 Request Matchers 来覆盖它。

以下是一个示例

namespace App\RequestMatcher;

use Kevinrob\GuzzleCache\Strategy\Delegate\RequestMatcherInterface;
use Psr\Http\Message\RequestInterface;

class ExampleOrgRequestMatcher implements RequestMatcherInterface
{

    /**
     * @inheritDoc
     */
    public function matches(RequestInterface $request)
    {
        return false !== strpos($request->getUri()->getHost(), 'example.org');
    }
}
namespace App\RequestMatcher;

use Kevinrob\GuzzleCache\Strategy\Delegate\RequestMatcherInterface;
use Psr\Http\Message\RequestInterface;

class TwitterRequestMatcher implements RequestMatcherInterface
{

    /**
     * @inheritDoc
     */
    public function matches(RequestInterface $request)
    {
        return false !== strpos($request->getUri()->getHost(), 'twitter.com');
    }
}
require_once __DIR__ . '/vendor/autoload.php';

use App\RequestMatcher\ExampleOrgRequestMatcher;
use App\RequestMatcher\TwitterRequestMatcher;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use Kevinrob\GuzzleCache\CacheMiddleware;
use Kevinrob\GuzzleCache\Strategy;

$strategy = new Strategy\Delegate\DelegatingCacheStrategy($defaultStrategy = new Strategy\NullCacheStrategy());
$strategy->registerRequestMatcher(new ExampleOrgRequestMatcher(), new Strategy\PublicCacheStrategy());
$strategy->registerRequestMatcher(new TwitterRequestMatcher(), new Strategy\PrivateCacheStrategy());

$stack = HandlerStack::create();
$stack->push(new CacheMiddleware($strategy));
$guzzle = new Client(['handler' => $stack]);

在这个示例中

  • 所有对 example.org 的请求将由 PublicCacheStrategy 处理
  • 所有对 twitter.com 的请求将由 PrivateCacheStrategy 处理
  • 所有其他请求将不会缓存。

Drupal

请参阅 Guzzle Cache 模块。

讨论此项目的链接

请我喝杯咖啡

如果您喜欢这个项目,您可以 请我喝杯咖啡!(或者一杯啤酒 😉)

开发

Docker 快速入门

初始化

make init

运行测试

make test

进入容器 shell

make shell