bvtterfly / replay
Laravel 中间件用于幂等性
Requires
- php: ^8.0
- illuminate/contracts: ^9.0
- spatie/laravel-package-tools: ^1.9.2
Requires (Dev)
- laravel/pint: ^1.1
- nunomaduro/collision: ^6.0
- nunomaduro/larastan: ^2.0.1
- orchestra/testbench: ^7.0
- pestphp/pest: ^1.21
- pestphp/pest-plugin-laravel: ^1.1
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
- phpunit/phpunit: ^9.5
- spatie/laravel-ray: ^1.26
- dev-main
- 1.3.0
- 1.2.0
- 1.1.3
- 1.1.2
- 1.1.1
- 1.1.0
- 1.0.0
- 0.1.0
- 0.0.1
- dev-dependabot/github_actions/aglipanci/laravel-pint-action-2.3.1
- dev-dependabot/github_actions/stefanzweifel/git-auto-commit-action-5
- dev-dependabot/github_actions/actions/checkout-4
- dev-dependabot/github_actions/ramsey/composer-install-2
This package is auto-updated.
Last update: 2024-03-05 14:45:48 UTC
README
🚨 该包已被废弃 🚨
我不再使用 Laravel,无法证明维护此包所需的时间。因此,我选择放弃它。请随意fork我的代码并维护自己的副本。
🔄 Replay - 幂等性中间件
此包可以轻松使您的端点具有幂等性。
查看有关幂等性的这篇 Stripe 博客文章。
实现灵感来源于 Stripe API。
💡 特点
- 通过添加中间件,轻松为您的 API 添加对幂等性请求的支持。
- 仅适用于
POST
请求。其他端点将被忽略。 - 仅记录和回放成功的(2xx)和服务器端错误(5xx)响应,而无需再次触摸您的控制器。
- 可以安全地重试,它不会记录带有客户端错误(4xx)的响应。
- 为了防止意外误用缓存的响应,请求的签名将得到验证,以确保使用相同的幂等性键和请求组合返回缓存的响应。
- 使用 Laravel 的原子锁来提供并发保护,以防止竞争条件。
安装
您可以通过 composer 安装此包
composer require bvtterfly/replay
您可以使用以下命令发布配置文件
php artisan vendor:publish --tag="replay-config"
这是已发布配置文件的内容
use Bvtterfly\Replay\StripePolicy; return [ /* |-------------------------------------------------------------------------- | Cache Store |-------------------------------------------------------------------------- | | This option controls the cache store that gets used while Replay will store the | information required for it to function. | By default, Replay will use the default cache store. | | Please see config/cache.php for the list of all available Cache Stores. | */ 'use' => env('REPLAY_CACHE_STORE', config('cache.default')), /* |-------------------------------------------------------------------------- | Replay Master Switch |-------------------------------------------------------------------------- | | Replay is enabled by default, | Use this setting to enable/disable the Replay. | */ 'enabled' => env('REPLAY_ENABLED', true), /* |-------------------------------------------------------------------------- | Expiration Seconds |-------------------------------------------------------------------------- | | This value controls the number of seconds until an idempotency response | is considered expired. | | The default is set to 1 day. | */ 'expiration' => 60 * 60 * 24, /* |-------------------------------------------------------------------------- | Request Header Name |-------------------------------------------------------------------------- | | Replay will check this header name to determine | if a request is an Idempotency request. | */ 'header_name' => 'Idempotency-Key', /* |-------------------------------------------------------------------------- | Response Header Name |-------------------------------------------------------------------------- | | Replay will add this header to previously executed responses | that's being replayed from the server. | | Use null or empty, if you don't need to identify these responses. | */ 'replied_header_name' => 'Idempotent-Replayed', /* |-------------------------------------------------------------------------- | Policy |-------------------------------------------------------------------------- | | The policy determines whether a request is idempotent and whether the response should | be recorded. | */ 'policy' => StripePolicy::class, ];
注意:Replay 需要支持 缓存标签 & 原子锁 功能的缓存驱动程序。请参阅 Laravel 文档,以查看您的驱动程序是否支持这些功能。
可选地,您可以使用以下命令发布翻译
php artisan vendor:publish --tag="replay-translations"
✨ 服务器使用
Bvtterfly\Replay\Replay
-中间件必须在内核中注册
//app/Http/Kernel.php protected $routeMiddleware = [ ... 'replay' => \Bvtterfly\Replay\Replay, ];
接下来,要使端点具有幂等性,请将 replay
中间件应用于它
Route::post('/payments', function () { // })->middleware('replay');
默认情况下,Replay 将幂等性键作为缓存键存储在缓存存储中,因此所有带有 replay 中间件的路由都使用与幂等性键相同的缓存键。在大多数情况下,这样存储是可行的,但在某些场景中,我们只需要将它们分开。在这些场景中,我们可以使用中间件参数添加缓存键的前缀
Route::post('/payments', function () { // })->middleware('replay:payments');
自定义策略
Replay 使用策略来确定请求是否幂等,以及是否应该记录响应。默认情况下,Replay 包含并使用 StripePolicy
策略。要创建自定义策略,您首先需要实现 \Bvtterfly\Replay\Contracts\Policy
接口
use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; interface Policy { public function isIdempotentRequest(Request $request): bool; public function isRecordableResponse(Response $response): bool; }
如果您想查看示例实现,请查看 StripePolicy
类。
要使用此策略,我们可以更改配置文件中的 policy
。
✨ 客户端使用
要执行幂等性请求,客户端必须向请求提供一个额外的 Idempotency-Key : <key>
标题,并使用一个唯一的键。
建议使用
- 为创建幂等性唯一键使用 "V4 UUIDs"(例如,
07cd2d27-e0dc-466f-8193-28453e9c3023
)。 - 从附加的用户对象中派生键,如购物车的 ID。这提供了一种相对简单的方式来防止重复提交。
一旦 Replay 检测到键,它将在缓存存储中查找它。如果找到,它将提供相同的响应,而无需再次调用控制器操作。
为了识别从服务器重新播放的先前执行响应,请查找头部 Idempotent-Replayed: true
。
如果重放找不到密钥,它会尝试获取缓存锁并缓存成功或服务器错误响应。然而,如果它无法获取锁,则另一个具有相同键的请求已在进行中,那么它将以HTTP冲突响应状态码响应。
重置缓存
如果您需要手动为此软件包重置缓存,可以使用以下Artisan命令
php artisan replay:cache-reset
🧪 测试
composer test
变更日志
请参阅变更日志获取有关最近更改的更多信息。
安全漏洞
请查阅我们的安全策略了解如何报告安全漏洞。
致谢
许可证
MIT许可证(MIT)。有关更多信息,请参阅许可证文件。