davihedg/idempotency
Composer 安装命令:
composer require davihedg/idempotency
包简介
Laravel middleware for idempotency
关键字:
README 文档
README
This package makes your endpoints idempotent easily.
Check out this Stripe Blog Post about Idempotency.
Implementation inspired by Stripe API.
💡 Features
- Adding support idempotency requests to your APIs easily by adding a middleware.
- Works only for
POSTrequests. Other endpoints are ignored. - Record and replay only successful(2xx) and server-side errors(5xx) responses, without touching your controller again.
- it's safe to retry, it doesn't record the response with client-side errors (4xx).
- To prevent accidental misuse of the cached responses, the request's signature is validated to ensure that the cached response is returned using the same combination of Idempotency-Key and Request.
- Concurrency protection using Laravel's atomic locks to prevent race conditions.
Installation
You can install the package via composer:
composer require bvtterfly/replay
You can publish the config file with:
php artisan vendor:publish --tag="replay-config"
This is the contents of the published config file:
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, ];
Note: Replay needs a cache driver that supports Cache Tags & Atomic Locks features. Refer to Laravel's documentation to see if your driver supports these features.
Optionally, you can publish the translations using
php artisan vendor:publish --tag="replay-translations"
✨ Server Usage
The Bvtterfly\Replay\Replay-middleware must be registered in the kernel:
//app/Http/Kernel.php protected $routeMiddleware = [ ... 'replay' => \Bvtterfly\Replay\Replay, ];
Next, For idempotent an endpoint, apply replay middleware to it:
Route::post('/payments', function () { // })->middleware('replay');
By default, Replay stores the idempotent key as a cache key in the cache store, So all routes with replay middleware share the same cache key with an idempotent key. It's Okay to store it this way in most cases, but in some scenarios, we just need to separate them. In these scenarios, we can add a prefix to cache keys using middleware parameters:
Route::post('/payments', function () { // })->middleware('replay:payments');
Custom Policy
Replay use Policy to determine whether a request is idempotent and whether the response should be recorded. By default, Replay includes and uses StripePolicy Policy.
To create your custom policy, you first need to implement the \Bvtterfly\Replay\Contracts\Policy contract:
use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; interface Policy { public function isIdempotentRequest(Request $request): bool; public function isRecordableResponse(Response $response): bool; }
If you want to view an example implementation take a look at the StripePolicy class.
For using this policy, We can change the policy in the config file.
✨ Client Usage
To perform an idempotent request, Client must provide an additional Idempotency-Key : <key> header with a unique key to the request.
it is recommended to:
- Use "V4 UUIDs" for the creation of the idempotency unique keys (e.g.
07cd2d27-e0dc-466f-8193-28453e9c3023). - Derive the key from a user-attached object, like the ID of a shopping cart. This provides a relatively straightforward way to protect against double submissions.
Once Replay detects a key, it'll look it up in cache store. If found, it will serve the same response without hitting your controller action again.
To identify a previously executed response that’s being replayed from the server, look for the header Idempotent-Replayed: true.
If Replay can't find the key, it attempts to acquire a cache lock and caches successful or server error responses. Still, if it can't acquire the lock, another request with the same key is already in progress, then it will respond with the HTTP Conflict response status code.
Resetting the Cache
If you need to manually reset the cache for this package, you may use the following artisan command:
php artisan replay:cache-reset
🧪 Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.
davihedg/idempotency 适用场景与选型建议
davihedg/idempotency 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 28 次下载、GitHub Stars 达 0, 最近一次更新时间为 2022 年 10 月 19 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「laravel」 「replay」 「bvtterfly」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 davihedg/idempotency 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 davihedg/idempotency 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 davihedg/idempotency 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Model State Machine
A package to generate hashids for Eloquent models
Laravel circuit breaker package
Enterprise-ready process tracking, replay, and AI-assisted debugging for Laravel applications.
Some dependencies used by other repositories to manage League of Legends replays
League of Legends replay downloader library
统计信息
- 总下载量: 28
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 14
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2022-10-19