mikespub/micheh-psr7-cache

PSR-7 HTTP 消息的缓存和条件请求辅助工具

2.0.0 2023-12-14 18:28 UTC

This package is auto-updated.

Last update: 2024-09-17 18:37:18 UTC


README

Latest Version on Packagist Software License Testing Total Downloads

此库提供了一个简单的方法,既可以向 PSR-7 HTTP 消息实现添加缓存相关的头部,也可以从 PSR-7 消息中提取缓存和条件请求信息(例如,如果响应可缓存)。它还提供了一个 Cache-Control 值对象,用于提供面向对象的接口来操作 Cache-Control 头部。

此分支(PHP 8.1+)的安装

使用 Composer 安装此库

$ composer require mikespub/micheh-psr7-cache

注意:原始包仍然可在 micheh/psr7-cache 获得,但不再维护

快速入门

要启用 HTTP 响应的缓存,创建一个 CacheUtil 实例,调用 withCache 方法并提供您的 PSR-7 响应。

/** @var \Psr\Http\Message\ResponseInterface $response */

$util = new \Micheh\Cache\CacheUtil();
$response = $util->withCache($response);

这将向您的响应添加头部 Cache-Control: private, max-age=600。具有此头部,响应只由发送请求的客户缓存,并缓存 600 秒(10 分钟)。在这段时间内,客户端应使用缓存中的响应,而无需向应用程序发送新的请求。

缓存验证器

应用程序还应将缓存验证器添加到响应中:一个 ETag 头部(如果您知道资源最后修改的时间,还有一个 Last-Modified 头部)。这样,客户端也会在请求中包含 ETagLast-Modified 信息,应用程序可以检查客户端是否仍然具有当前状态。

/** @var \Psr\Http\Message\ResponseInterface $response */

$util = new \Micheh\Cache\CacheUtil();
$response = $util->withCache($response);
$response = $util->withETag($response, 'my-etag');
$response = $util->withLastModified($response, new \DateTime());

重新验证响应

要确定客户端是否仍然具有页面的当前副本且响应未修改,可以使用 isNotModified 方法。只需将缓存头部添加到响应中,然后调用该方法并传递请求和响应。该方法将自动比较请求的 If-None-Match 头部与响应的 ETag 头部(如果可用,请求的 If-Modified-Since 头部与响应的 Last-Modified 头部)。如果响应未修改,则返回带有缓存头部和状态码 304(未修改)的空响应。这将指示客户端使用之前请求的缓存副本,从而节省 CPU/内存使用和带宽。因此,为了提高性能,在 isNotModified 调用之前,应尽可能保持代码尽可能轻量。不要在此方法之前创建完整的响应。

/** @var \Psr\Http\Message\RequestInterface $request */
/** @var \Psr\Http\Message\ResponseInterface $response */

$util = new \Micheh\Cache\CacheUtil();
$response = $util->withCache($response);
$response = $util->withETag($response, 'my-etag');
$response = $util->withLastModified($response, new \DateTime());

if ($util->isNotModified($request, $response)) {
    return $response->withStatus(304);
}

// create the body of the response

使用不安全方法的条件请求

虽然上述过程通常是可选的,并且适用于安全方法(GET 和 HEAD),但也可以强制客户端具有当前资源状态。这对于不安全方法(例如 POST、PUT、PATCH 或 DELETE)很有用,因为这可以防止更新丢失(例如,如果另一个客户端在您的请求之前更新了资源)。一个好的做法是,最初使用 hasStateValidator 方法检查请求是否包含适当的头部(对于 ETagIf-Match 以及/或对于 Last-Modified 日期的 If-Unmodified-Since)。如果请求不包含此信息,则中止执行并返回状态码 428(预处理要求)或如果只想使用原始状态码,则返回状态码 403(禁止)。

/** @var \Psr\Http\Message\RequestInterface $request */

$util = new \Micheh\Cache\CacheUtil();
if (!$util->hasStateValidator($request)) {
    return $response->withStatus(428);
}

如果请求中包含了状态验证器,您可以使用hasCurrentState方法来检查请求是否包含当前资源状态,而不是过时的版本。如果请求包含过时的资源状态(另一个ETag或较旧的Last-Modified日期),则终止执行并返回状态码412(预条件失败)。否则,您可以继续处理请求并更新/删除资源。一旦资源被更新,最好在响应中包含更新的ETag(以及如果有的话,Last-Modified日期)。

/** @var \Psr\Http\Message\RequestInterface $request */
/** @var \Psr\Http\Message\ResponseInterface $response */

$util = new \Micheh\Cache\CacheUtil();
if (!$util->hasStateValidator($request)) {
    return $response->withStatus(428);
}

$eTag = 'my-etag'
$lastModified = new \DateTime();
if (!$util->hasCurrentState($request, $eTag, $lastModified)) {
    return $response->withStatus(412);
}

// process the request

可用的辅助方法

参考

许可证

本存档中的文件采用BSD-3-Clause许可证。您可以在LICENSE.md中找到此许可证的副本。