ميكيه / psr7-cache
PSR-7 HTTP 消息的缓存和条件请求助手
Requires
- php: >=5.4
- psr/http-message: ~1.0
Requires (Dev)
- phpunit/phpunit: ~4.0||~5.0
README
此库提供了一种简单的方法来为 PSR-7 HTTP 消息实现添加与缓存相关的头信息,或者从 PSR-7 消息中提取缓存和条件请求信息(例如,如果响应可缓存)。它还提供了一个 Cache-Control
值对象,以提供用于操作 Cache-Control
头的对象化接口。
安装
使用 Composer 安装此库
$ composer require 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
头信息)。这样,客户端也会在请求中包含 ETag
和 Last-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
方法最初检查请求是否包含适当的头信息(对于ETag
使用If-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
可用的辅助方法
方法 | 描述(更多信息请参阅phpDoc) |
---|---|
withCache |
添加Cache-Control 头的便利方法,允许缓存 |
withCachePrevention |
防止缓存的便利方法 |
withExpires |
从一个时间戳、字符串或DateTime添加Expires 头 |
withRelativeExpires |
添加具有特定生命周期的Expires 头 |
withETag |
添加ETag 头 |
withLastModified |
从一个时间戳、字符串或DateTime添加Last-Modified 头 |
withCacheControl |
从字符串或值对象添加Cache-Control 头 |
hasStateValidator |
检查是否可以确定资源状态 |
hasCurrentState |
检查请求是否具有当前资源状态 |
isNotModified |
检查响应是否未修改 |
isCacheable |
检查响应是否可由公共缓存缓存 |
isFresh |
检查响应是否新鲜(年龄小于生命周期) |
getLifetime |
返回响应的寿命(应缓存多久) |
getAge |
返回响应的年龄(在缓存中存在了多久) |
参考
许可
此存档中的文件受BSD-3-Clause许可的许可。您可以在LICENSE.md中找到此许可证的副本。