werk365/etagconditionals

Laravel 包,用于启用对 ETags 的支持,并处理 If-Match 和 If-None-Match 条件请求

1.4.2 2023-03-22 10:32 UTC

README

Latest Version on Packagist Total Downloads StyleCI Scrutinizer Code Quality Build Status

此包提供了一套中间件,用于设置 ETags 并处理 HTTP 条件请求

目前支持 If-None-MatchedIf-Match

该包旨在提供工具,以在用 Laravel 构建API时提供更好的客户端缓存,以及防止空中碰撞。

当使用此包并启用中间件时,您的客户端(浏览器)将自动处理由 ETagIf-None-Match 标头提供的缓存。

安装

通过 Composer

$ composer require werk365/etagconditionals

用法

您可以使用中间件组,自动应用所有可用中间件(例如,如果您使用 apiResource 路由,则推荐这样做),通过设置 etag 中间件,或单独应用中间件。

当前可用中间件

  • setEtag
  • ifMatch
  • ifNoneMatch

setEtag

方法:任何

此中间件将在您的响应上设置 ETag 标头。 ETag 标头等于 $response->getContent() 的 md5 哈希。 支持通过将请求转换为 GET 请求并更改响应来处理 HEAD 请求。

ifMatch

方法:PATCH

此中间件将创建一个新请求到端点的 GET 等效项,并检索当前内容。之后,将比较当前内容的哈希和 If-Match 哈希。如果哈希匹配,则通过中间件允许 PATCH 请求,如果不匹配,则返回 412

重要 由于内部创建的 GET 请求也将通过启用的中间件,您可能会遇到一些问题。例如:如果您有一个未应用于 If-Match etag 所属的响应体的中间件,这将导致哈希不匹配。

对于此场景,此中间件设置一个 X-From-Middleware: IfMatch 标头,您可以在其他中间件中使用它来过滤这些请求。请注意,由于此标头也可能由客户端设置,因此永远不要用它来跳过重要操作,如身份验证中间件。

ifNoneMatch

方法:GET|HEAD

此中间件将简单地比较提交的 If-None-Match 标头与响应的新创建的 etag。如果没有匹配,则返回 200,在 GET 请求的情况下返回新的响应。如果哈希匹配,则返回 304,不带内容,允许浏览器使用缓存的内容。

比较算法

默认情况下,将使用弱比较算法为 IfMatchIfNoneMatch ETags。在实践中,这意味着我们简单地从 ETag 中删除任何 W/ 标签,以便它们可以与中间件中创建的正常标签进行比较。这是为了支持某些配置自动将 W/ 标签添加到我们提供的 ETag 的情况。

可以通过发布配置文件来更改此行为

$ php artisan vendor:publish --provider="Werk365\EtagConditionals\EtagConditionalsServiceProvider"

然后更改以下值

return [
    'if_match_weak' => env('IF_MATCH_WEAK', true),
    'if_none_match_weak' => env('IF_NONE_MATCH_WEAK', true),
];

或者通过设置上面的ENV值。

定义自定义ETags

静态方法 EtagConditionals::etagGenerateUsing() 允许您通过传递回调函数作为参数,完全控制ETag的生成方式。这意味着您可以使用不同的算法返回ETag,或者采用其他自定义解决方案。

        EtagConditionals::etagGenerateUsing(function (\Symfony\Component\HttpFoundation\Response $response) {
            return hash('sha256', $response->getContent());
        });
        EtagConditionals::etagGenerateUsing(function (\Illuminate\Http\Request $request, \Symfony\Component\HttpFoundation\Response $response) {
            return Cache::rememberForever('etag.'.$request->url(), function () use ($response) {
                 return md5($response->getContent());
            });
        });

变更日志

请参阅变更日志,了解最近的变化信息。

贡献

请随时创建问题和提交pull请求。对于提交的任何PR,请确保它已通过测试或包括新的测试。

安全

如果您发现任何与安全相关的问题,请通过作者电子邮件联系,而不是使用问题跟踪器。

致谢

许可

请参阅许可文件获取更多信息。