TL;DR
Üstel geri çekilmeli yeniden deneme (5-10 deneme), değişmezlik anahtarları, HMAC imza doğrulaması ve 5 saniyelik zaman aşımları ile güvenilir webhook'lar tasarlayın. Hemen 2xx döndürün, asenkron olarak işleyin. Modern PetstoreAPI, sipariş güncellemeleri, evcil hayvan sahiplenmeleri ve ödeme bildirimleri için tam yeniden deneme ve güvenlikle webhook'lar uygulamaktadır.
Giriş
Bir müşteriye evcil hayvanının sahiplenildiğini bildirmek için bir webhook gönderirsiniz. Müşterinin sunucusu kapalıdır. Webhook'unuz başarısız olur. Yeniden dener misiniz? Kaç kez? Peki ya müşteri webhook'u iki kez alır ve müşteriyi iki kez ücretlendirirse?
Webhook'lar, olayları istemci URL'lerine ileten HTTP geri aramalarıdır. Teoride basit olsalar da pratikte karmaşıktırlar. Ağlar başarısız olur, sunucular çöker ve istemcilerde hatalar bulunur. Üretimdeki webhook'lar yeniden deneme mantığına, değişmezliğe, güvenliğe ve izlemeye ihtiyaç duyar.
Modern PetstoreAPI, sipariş güncellemeleri, evcil hayvan sahiplenmeleri ve ödeme bildirimleri için üretime hazır webhook'lar uygulamaktadır. Her webhook, yeniden deneme mantığı, imza doğrulama ve değişmezlik içerir.
Bu kılavuzda, Modern PetstoreAPI desenlerini kullanarak güvenilir webhook'ları nasıl tasarlayacağınızı öğreneceksiniz.
Webhook Temelleri
Webhook'lar, olaylar meydana geldiğinde istemci tarafından sağlanan URL'lere gönderilen HTTP POST istekleridir.
Webhook'lar Nasıl Çalışır
1. İstemci webhook URL'sini kaydeder:
POST /webhooks
{
"url": "https://client.com/webhooks/petstore",
"events": ["pet.adopted", "order.completed"]
}
2. Olay meydana gelir (evcil hayvan sahiplenildi)
3. Sunucu webhook gönderir:
POST https://client.com/webhooks/petstore
Content-Type: application/json
X-Webhook-Signature: sha256=abc123...
{
"event": "pet.adopted",
"data": {
"petId": "019b4132",
"userId": "user-456",
"timestamp": "2026-03-13T10:30:00Z"
}
}
4. İstemci yanıt verir:
200 OK
Güvenilirlik Sorunu
Webhook'lar birçok nedenden dolayı başarısız olabilir:
- İstemci sunucusu kapalı
- Ağ zaman aşımı
- İstemci 500 hatası döndürüyor
- İstemci yavaş (30 saniye sürüyor)
- İstemci webhook'u alır ancak işlemeden önce çöker
Yeniden deneme mantığı olmadan olaylar kaybolur. Değişmezlik olmadan, yinelenen webhook'lar yinelenen eylemlere neden olur.
Üstel Geri Çekilmeli Yeniden Deneme Mantığı
Başarısız olan webhook'ları artan gecikmelerle yeniden deneyin.
Üstel Geri Çekilme Stratejisi
Deneme 1: Anında
Deneme 2: 1 saniye sonra
Deneme 3: 2 saniye sonra
Deneme 4: 4 saniye sonra
Deneme 5: 8 saniye sonra
Deneme 6: 16 saniye sonra
Neden üstel? Eğer istemci kapalıysa, yeniden denemelerle onu zorlamak yardımcı olmaz. Üstel geri çekilme, iyileşme için zaman tanır.
Uygulama
async function sendWebhook(url, payload, attempt = 1, maxAttempts = 6) {
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Webhook-Signature': generateSignature(payload)
},
body: JSON.stringify(payload),
timeout: 5000 // 5 second timeout
});
if (response.ok) {
return { success: true, attempt };
}
// Retry on 5xx errors
if (response.status >= 500 && attempt < maxAttempts) {
const delay = Math.pow(2, attempt - 1) * 1000;
await sleep(delay);
return sendWebhook(url, payload, attempt + 1, maxAttempts);
}
// Don't retry 4xx errors (client error)
return { success: false, status: response.status };
} catch (error) {
// Network error or timeout - retry
if (attempt < maxAttempts) {
const delay = Math.pow(2, attempt - 1) * 1000;
await sleep(delay);
return sendWebhook(url, payload, attempt + 1, maxAttempts);
}
return { success: false, error: error.message };
}
}
Ne Zaman Yeniden Denenmeli
Şu durumlarda yeniden deneyin:
- 5xx sunucu hataları (500, 502, 503, 504)
- Ağ zaman aşımları
- Bağlantı reddedildi
- DNS hataları
Şu durumlarda yeniden denemeyin:
- 4xx istemci hataları (400, 401, 404) - istemci bunları düzeltmez
- 2xx başarı - zaten başarılı oldu
Dead Letter Queue (Ölü Mektup Kuyruğu)
Maksimum yeniden deneme sayısından sonra, başarısız webhook'ları manuel inceleme için bir dead letter queue'ya taşıyın:
if (!result.success) {
await deadLetterQueue.add({
url,
payload,
attempts: maxAttempts,
lastError: result.error,
timestamp: new Date()
});
}
Yinelenenleri Önlemek İçin Değişmezlik
İstemciler aynı webhook'u birden çok kez alabilir. Değişmezlik, yinelenen işlemleri önler.
Değişmezlik Anahtarları
Her webhook ile benzersiz bir kimlik ekleyin:
{
"id": "webhook_019b4132",
"event": "pet.adopted",
"data": {...}
}
İstemci işlenen kimlikleri depolar:
app.post('/webhooks/petstore', async (req, res) => {
const webhookId = req.body.id;
// Check if already processed
const processed = await db.webhooks.findOne({ id: webhookId });
if (processed) {
return res.status(200).json({ message: 'Already processed' });
}
// Process webhook
await processPetAdoption(req.body.data);
// Mark as processed
await db.webhooks.insert({ id: webhookId, processedAt: new Date() });
res.status(200).json({ message: 'Processed' });
});
Değişmez İşlemler
İşlemleri değişmez olacak şekilde tasarlayın:
Kötü (değişmez değil):
// İki kez ücretlendirme, çifte ücretlendirmeye neden olur
await chargeCustomer(userId, amount);
İyi (değişmez):
// Değişmezlik anahtarıyla ücretlendirme, çifte ücretlendirmeyi önler
await chargeCustomer(userId, amount, { idempotencyKey: webhookId });
Güvenlik İçin İmza Doğrulaması
Webhook'ların bir saldırgandan değil, API'nizden geldiğini doğrulayın.
HMAC İmzası
Paylaşılan sırrı kullanarak imza oluşturun:
// Sunucu imza oluşturur
const crypto = require('crypto');
function generateSignature(payload, secret) {
const hmac = crypto.createHmac('sha256', secret);
hmac.update(JSON.stringify(payload));
return hmac.digest('hex');
}
// Başlığa ekleyin
headers['X-Webhook-Signature'] = `sha256=${generateSignature(payload, webhookSecret)}`;
İstemci imzayı doğrular:
function verifySignature(payload, signature, secret) {
const expected = generateSignature(payload, secret);
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(`sha256=${expected}`)
);
}
app.post('/webhooks/petstore', (req, res) => {
const signature = req.headers['x-webhook-signature'];
if (!verifySignature(req.body, signature, WEBHOOK_SECRET)) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Webhook'u işle
...
});
Zaman Damgası Doğrulaması
Tekrar saldırılarını önlemek için zaman damgası ekleyin:
{
"id": "webhook_019b4132",
"timestamp": "2026-03-13T10:30:00Z",
"event": "pet.adopted",
"data": {...}
}
Eski webhook'ları reddedin:
const webhookAge = Date.now() - new Date(req.body.timestamp);
if (webhookAge > 5 * 60 * 1000) { // 5 minutes
return res.status(400).json({ error: 'Webhook too old' });
}
Zaman Aşımı Yönetimi
Yavaş istemcilerin sisteminizi engellemesini önlemek için agresif zaman aşımları ayarlayın.
5 Saniyelik Zaman Aşımı
const response = await fetch(url, {
method: 'POST',
body: JSON.stringify(payload),
timeout: 5000 // 5 seconds
});
Neden 5 saniye? Webhook'lar hemen dönmelidir. Eğer bir istemci daha uzun sürerse, senkron işlem yapıyor demektir (yanlış desen).
Asenkron İşleme Deseni
Kötü (senkron):
app.post('/webhooks/petstore', async (req, res) => {
// Bu işlem 30 saniye sürer - webhook zaman aşımına uğrar
await processOrder(req.body.data);
await sendEmail(req.body.data);
await updateInventory(req.body.data);
res.status(200).json({ message: 'Processed' });
});
İyi (asenkron):
app.post('/webhooks/petstore', async (req, res) => {
// Hemen dön
res.status(200).json({ message: 'Received' });
// Asenkron olarak işle
queue.add('process-webhook', req.body);
});
Modern PetstoreAPI Webhook'ları Nasıl Uygular
Modern PetstoreAPI, üretime hazır webhook'lar uygulamaktadır.
Webhook Olayları
pet.adopted - Evcil hayvan sahiplenildi
pet.status_changed - Evcil hayvan durumu değişti
order.created - Sipariş oluşturuldu
order.completed - Sipariş tamamlandı
payment.succeeded - Ödeme başarılı
payment.failed - Ödeme başarısız
Webhook Payload
{
"id": "webhook_019b4132-70aa-764f-b315-e2803d882a24",
"event": "pet.adopted",
"timestamp": "2026-03-13T10:30:00Z",
"data": {
"petId": "019b4132-70aa-764f-b315-e2803d882a24",
"userId": "user-456",
"orderId": "order-789",
"adoptionDate": "2026-03-13"
},
"apiVersion": "v1"
}
Yeniden Deneme Yapılandırması
- Maksimum deneme: 10
- Geri çekilme: Üstel (1s, 2s, 4s, 8s, 16s, 32s, 64s, 128s, 256s, 512s)
- Toplam yeniden deneme süresi: ~17 dakika
- Maksimum yeniden denemeden sonra dead letter queue
Güvenlik
X-Webhook-Signaturebaşlığında HMAC-SHA256 imzası- Zaman damgası doğrulaması (> 5 dakikadan eski olanları reddet)
- Webhook URL'leri için HTTPS gereklidir
Apidog ile Webhook'ları Test Etme
Apidog, webhook testini destekler.
Webhook Teslimatını Test Et
- Apidog'da sahte (mock) webhook uç noktası oluşturun
- Uç noktayı PetstoreAPI'ye kaydedin
- Olayı tetikleyin (evcil hayvan sahiplen)
- Webhook'un alındığını doğrulayın
- Payload formatını kontrol edin
İmza Doğrulamasını Test Et
// Apidog test script
const signature = pm.request.headers.get('X-Webhook-Signature');
const payload = pm.request.body.raw;
const secret = pm.environment.get('WEBHOOK_SECRET');
const expected = generateSignature(payload, secret);
pm.test('Signature valid', () => {
pm.expect(signature).to.equal(`sha256=${expected}`);
});
Yeniden Deneme Mantığını Test Et
- Sahte uç noktadan 500 hatası döndürün
- Üstel geri çekilme ile yeniden deneme girişimlerini doğrulayın
- Maksimum yeniden denemeden sonra dead letter queue'yu kontrol edin
Değişmezliği Test Et
- Webhook'u alın
- 200 döndürün
- Aynı webhook'u tekrar alın (simüle edilmiş yeniden deneme)
- Yinelenen işlem olmadığını doğrulayın
Sonuç
Güvenilir webhook'lar şunları gerektirir:
- Üstel geri çekilmeli yeniden deneme (5-10 deneme)
- Yinelenmeleri önlemek için değişmezlik anahtarları
- Güvenlik için HMAC imza doğrulaması
- 5 saniyelik zaman aşımları
- İstemci tarafında asenkron işleme
- Başarısız webhook'lar için dead letter queue
Modern PetstoreAPI tüm bu desenleri uygulamaktadır. Tam örnekler için webhook belgelerini kontrol edin.
Üretime geçmeden önce yeniden deneme mantığını, imzaları ve değişmezliği doğrulamak için webhook'larınızı Apidog ile test edin.
SSS
Webhook'lar kaç kez yeniden deneme yapmalıdır?
Üstel geri çekilme ile 5-10 deneme. Bu, istemciyi aşırı yüklemeden geçici kesintileri (5-17 dakika) kapsar.
Webhook'lar 4xx hatalarında yeniden deneme yapmalı mı?
Hayır. 4xx hataları istemci sorunlarını (hatalı URL, kimlik doğrulama hatası) gösterir. Yeniden denemek bunları düzeltmez. Yalnızca 5xx hatalarını ve ağ arızalarını yeniden deneyin.
Webhook zaman aşımları ne kadar olmalı?
Maksimum 5 saniye. İstemciler hemen 200 döndürmeli ve asenkron olarak işlem yapmalıdır. Daha uzun zaman aşımları, istemcinin senkron işlem yaptığını gösterir.
Bir istemci webhook'lara hiç yanıt vermezse ne olur?
Maksimum yeniden denemeden sonra, dead letter queue'ya taşıyın. Müşteriyi e-posta ile uyarın. Tekrarlanan başarısızlıkların ardından o istemci için webhook'ları devre dışı bırakmayı düşünün.
Webhook URL'leri HTTPS olmalı mı?
Evet, her zaman HTTPS gereklidir. HTTP webhook'lar yakalanabilir ve değiştirilebilir. Modern PetstoreAPI, HTTP webhook URL'lerini reddeder.
Tekrar saldırılarını nasıl önlersiniz?
Payload'a zaman damgası ekleyin ve 5 dakikadan eski webhook'ları reddedin. İmza doğrulamasıyla birleştirin.
İstemciler webhook'un yeniden teslimini talep edebilir mi?
Evet. Modern PetstoreAPI, belirli webhook'ları yeniden teslim etmek için bir uç nokta sağlar: POST /webhooks/{id}/redeliver
Webhook'ları yerel olarak nasıl test edersiniz?
Geliştirme sırasında localhost'u internete açmak için ngrok gibi araçları kullanın veya webhook uç noktalarını simüle etmek için Apidog'un sahte sunucusunu kullanın.
