Laravel Idempotency: middleware для идемпотентных HTTP-запросов

Вендэлл Адриэль представил пакет Laravel Idempotency, который добавляет поддержку идемпотентности для write-запросов в Laravel. При повторной отправке POST, PUT или PATCH с тем же ключом и тем же payload пакет возвращает закэшированный ответ вместо повторного выполнения обработчика. Это используется в сценариях с платежами, созданием заказов и других API, где возможны повторы из-за сетевых сбоев.

Подключение middleware

Пакет можно применить к маршруту через стандартный middleware:

use WendellAdriel\Idempotency\Http\Middleware\Idempotent;

Route::post('/orders', StoreOrderController::class)
    ->middleware(Idempotent::class);

Middleware ожидает заголовок Idempotency-Key. Если тот же ключ приходит повторно с идентичными данными, возвращается исходный ответ с дополнительным заголовком Idempotency-Replayed: true.

Настройки можно задать на уровне маршрута:

Route::post('/payments', ChargePaymentController::class)->middleware(
    Idempotent::using(
        ttl: 600,
        lockTimeout: 30,
        required: false,
        scope: \WendellAdriel\Idempotency\Enums\IdempotencyScope::Ip,
        header: 'X-Idempotency-Key',
    )
);

Также доступен вариант через PHP-атрибуты для класса или метода контроллера:

use WendellAdriel\Idempotency\Attributes\Idempotent;
use WendellAdriel\Idempotency\Enums\IdempotencyScope;

#[Idempotent]
class PaymentController
{
    #[Idempotent(ttl: 600, lockTimeout: 30, scope: IdempotencyScope::Ip)]
    public function store()
    {
        // ...
    }
}

Атрибут наследует поведение стандартных middleware Laravel, поэтому поддерживаются параметры only и except.

Область действия ключей

Ключи идемпотентности могут работать в разных областях, которые настраиваются глобально или для конкретного маршрута:

  • user - ключи разделяются по пользователям, для гостей используется IP

  • ip - разделение по IP-адресу

  • global - один ключ действует для всех пользователей и IP

Обработка конфликтов

Пакет обрабатывает два типа конфликтов. Если приходит тот же ключ, но с другим payload, возвращается ошибка 422 Unprocessable Entity.

Если второй идентичный запрос поступает до завершения первого, возвращается 409 Conflict с заголовком Retry-After: 1.

Обе ситуации реализованы через атомарные блокировки кеша, поэтому требуется драйвер с поддержкой lock, например Redis или Memcached.

Artisan-команды

Пакет добавляет команды для работы с кешированными записями. Просмотр активных записей:

php artisan idempotency:list --scope=user --id=5

Удаление записей:

# удалить все записи пользователя
php artisan idempotency:forget --scope=user --id=5 --force

# удалить записи по ключу
php artisan idempotency:forget --key=checkout-1 --force

Команда удаления требует подтверждения, если не указан флаг --force.

Похожие статьи

Рекомендательные технологии Подробнее
Технологии и IT-новости 7 месяцев назад

Новая натрий-ионная батарея делает ставку на древесину

Новая натрий-ионная батарея, в которой в качестве ключевого материала используется лигнин — побочный продукт деревообработки. Технология обещает снизить стоимость аккумуляторов и уменьшить зависимость от дефицитных металлов.

Пауза всех очередей Laravel во время деплоя

Laravel 13.25 добавляет возможность поставить на паузу все очереди приложения одной командой. Разбираем команды queue:pause --all и queue:resume --all, работу глобальной паузы, взаимодействие с индивидуальными паузами и новые события.

Технологии и IT-новости 8 месяцев назад

1X отправляет своих "домашних" гуманоидов на заводы и склады

Компания 1X объявила о партнёрстве с инвестиционной группой EQT, благодаря которому домашние гуманоиды Neo будут поставлены на производство и склады. Это стратегический шаг, позволяющий расширить применение роботов за пределы бытового использования.

Технологии и IT-новости 6 месяцев назад

Apple начала тестировать сквозное шифрование RCS‑сообщений в iOS 26.4

Apple начала тестировать сквозное шифрование сообщений по протоколу RCS в бета‑версии iOS 26.4. Новая функция призвана усилить безопасность переписки, но пока работает только между устройствами Apple и будет доступна в будущем обновлении.