StudyCode
Идемпотентный метод при повторном выполнении даёт то же состояние сервера, что и при первом. Идемпотентны GET, HEAD, PUT, DELETE (повторное удаление уже удалённого ничего не меняет), не идемпотентен POST — два POST /orders создадут два заказа. Это важно для ретраев: если запрос оборвался по таймауту, клиент не знает, применился ли он; идемпотентный запрос можно смело повторить, а повтор POST рискует создать дубль. Поэтому платёжные API добавляют idempotency key: сервер запоминает ключ первого запроса и на повтор с тем же ключом возвращает сохранённый ответ вместо повторного списания.
// Проблема: таймаут — заказ создан или нет? Повтор = дубль?
await fetch('/api/orders', { method: 'POST', body });
// Решение: idempotency key
await fetch('/api/orders', {
method: 'POST',
headers: { 'Idempotency-Key': 'order-7f3a-attempt' },
body,
});
// На сервере
app.post('/api/orders', async (req, res) => {
const key = req.headers['idempotency-key'];
const saved = await db.idempotency.find(key);
if (saved) return res.json(saved.response); // повтор — тот же ответ
const order = await createOrder(req.body);
await db.idempotency.save(key, { response: order });
res.status(201).json(order);
});