REST API'lerinde Hata Yönetimi: Sağlam ve Test Edilebilir Hata Sözleşmeleri
API'nizin hata yanıtları, sözleşmesinin bir parçasıdır. Müşteriler bunları ayrıştırır, yeniden deneme mantığı bunlara göre dallanır ve destek mühendisleri sabahın 2'sinde bunları arar. Ancak çoğu ekip başarılı yolu ayrıntılı olarak tasarlarken hataların çerçevenin varsayılan davranışına kalmasına izin verir. Sonuçta aynı API'de üç farklı hata şekli, "success": false içeren 200 yanıtları ve veritabanı şemanızı internete sızdıran yığın izleri ortaya çıkar.
Bu rehber REST hizmetleri için uçtan uca API hata yönetimini ele alır:
- Doğru HTTP durum kodunu seçme
- RFC 9457 Problem Details ile tek bir hata gövdesi kullanma
- Makine tarafından okunabilir kodları insan mesajlarından ayırma
- Hataları yeniden denenebilir veya terminal olarak işaretleme
- Sırları hata yanıtlarından uzak tutma
- Apidog ile her hata yolunu test etme
Bu yaklaşım, REST API'lerinin hangi HTTP durum kodlarını kullanması gerektiğine ilişkin incelemeyi, sözleşme düzeyindeki ek kararlarla tamamlar.
Gövdeyle değil, durum koduyla başlayın
HTTP, ilk hata semantiği katmanını zaten sağlar. RFC 9110, durum kodu ailelerini şöyle tanımlar:
- 4xx: İstemci yanlış bir şey yaptı; aynı istek büyük olasılıkla tekrar başarısız olur.
- 5xx: Sunucu başarısız oldu; istemcinin isteği doğru olabilir.
Genel istemciler, proxy'ler, önbellekler ve yeniden deneme kütüphaneleri JSON gövdenizi okumadan önce bu ayrımı kullanır. Bu nedenle hata gövdesini tasarlamadan önce durum kodunu doğru seçin.
Tasarım sırasında MDN HTTP durum kodu referansını açık tutun:
| Durum | Kullan | Kullanmayın | Neden |
|---|---|---|---|
| 400 Hatalı İstek | Bozuk JSON, yanlış içerik türü veya eksik zorunlu alan | 422 | Sunucu isteği ayrıştıramıyor veya anlayamıyor |
| 422 İşlenemeyen İçerik | İyi biçimlendirilmiş ancak anlamsal olarak geçersiz istek; örneğin negatif miktar veya desteklenmeyen para birimi | 400 | Sözdizimi doğru, değerler yanlış |
| 401 Yetkilendirilmemiş | Kimlik bilgisi yok, süresi dolmuş veya geçersiz belirteç | 403 | İstemci kimliğini kanıtlamadı; WWW-Authenticate gönderin |
| 403 Yasak | Kimliği doğrulanmış ancak yeterli izni olmayan istemci | 401 | Kimlik biliniyor, erişim reddedildi |
| 404 Bulunamadı | Kaynak hiç var olmadı veya varlığı doğrulanmayacak | 410 | Güvenli varsayılandır; kaynağı yetkisiz araştırmalardan gizler |
| 410 Kaldırıldı | Kaynak vardı ve kasıtlı, kalıcı olarak silindi | 404 | İstemcilere ve tarayıcılara referanslarını silmelerini bildirir |
| 409 Çakışma | Yinelenen anahtar, eski sürüm veya düzenleme çakışması | 400 | İstek geçerli ancak mevcut kaynak durumuyla çakışıyor |
| 429 Çok Fazla İstek | İstemci hız limitini aştı | 503 | Her zaman Retry-After ekleyin |
| 500 Dahili Sunucu Hatası | Kodunuzda işlenmemiş istisna | 502 | Sunucunuzda beklenmeyen bir hata oluştu |
| 502 Hatalı Ağ Geçidi | Yukarı akış hizmeti ağ geçidine geçersiz yanıt döndürdü | 500 | Hata ağ geçidinin arkasındaki hizmette |
| 503 Hizmet Kullanılamıyor | Sunucu aşırı yüklü veya bakımda | 500 | Tanım gereği geçicidir; mümkünse Retry-After ekleyin |
| 504 Ağ Geçidi Zaman Aşımı | Yukarı akış hizmetinin yanıt süresi doldu | 500 | Yavaş bağımlılığı bozuk koddan ayırır |
İki ayrım özellikle önemlidir:
- 401 ve 403 arasındaki fark bir güvenlik sınırıdır. Kimliği doğrulanmamış bir arayana 403 döndürmek, kaynağın var olduğunu sızdırabilir.
-
429 yanıtında
Retry-Afterolmaması istemcileri sıkı yeniden deneme döngülerine itebilir. API hız limitlendirme rehberimiz, başlık matematiğini ve kullanılan algoritmaları açıklar.
Tek hata gövdesi şekli: RFC 9457 Problem Details
Durum kodu doğru seçildikten sonra API'nizin tüm hataları tek bir medya türünü ve şemayı paylaşmalıdır. Standart yaklaşım, application/problem+json olarak sunulan RFC 9457 Problem Details'tir.
Beş temel alan bulunur:
-
type: Hata kategorisini tanımlayan URI -
title: Kısa, insan tarafından okunabilir özet -
status: HTTP durum kodunun gövdedeki karşılığı -
detail: Bu olayda neyin yanlış gittiği -
instance: Bu başarısızlığa özgü URI
Diğer alanlar özel uzantı üyeleri olarak eklenir. Örneğin bir ödeme doğrulama hatası:
POST /v1/payments HTTP/1.1
Content-Type: application/json
{ "amount": -1400, "currency": "USD", "source": "card_8xKt2" }
HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json
{
"type": "https://api.example.com/problems/validation-error",
"title": "İstek doğrulaması başarısız oldu",
"status": 422,
"detail": "Bir veya daha fazla alan doğrulama hatası verdi.",
"instance": "/v1/payments/requests/req_9f3c1a7b",
"code": "PAYMENT_VALIDATION_FAILED",
"errors": [
{
"field": "amount",
"code": "AMOUNT_NOT_POSITIVE",
"message": "miktar, küçük birimlerde pozitif bir tamsayı olmalıdır"
}
],
"request_id": "req_9f3c1a7b"
}
errors[] bir uzantı üyesidir ve istemcilerin özellikle işine yarar. Ön uç, tek bir genel hata afişi göstermek yerine her hatayı ilgili form alanına bağlayabilir.
Alan yolları için tek bir gösterim seçin ve tutarlı kalın:
- JSON Pointer
- Noktalı yollar
Her hata için bu şekli kullanın; buna çerçeve veya ağ geçidi tarafından üretilen hatalar da dahildir. Aksi halde istemciler hem Problem Details hem de ağ geçidinin HTML hata sayfası için ayrı ayrıştırıcılar yazmak zorunda kalır.
Daha fazla ayrıntı için RFC 9457 açıklayıcımıza bakabilirsiniz. Rehber, üyeleri, kayıt kurallarını ve RFC 7807'nin yerini nasıl aldığını açıklar.
Makine tarafından okunabilir kodlar ve insan mesajları
Örnekte hem code hem de message alanları bulunması bilinçli bir tercihtir. Bu alanlar farklı kitlelere hizmet eder ve tek bir dizeye indirgenmemelidir.
Makine tarafından okunabilir kodlar
AMOUNT_NOT_POSITIVE, CURRENCY_UNSUPPORTED ve IDEMPOTENCY_KEY_REUSED gibi kodlar sözleşmenin parçasıdır. Bu nedenle:
- Kararlı olmalıdır.
- Belgelenmelidir.
- Numaralandırılabilir veya kategorize edilebilir olmalıdır.
- İstemcilerin dallanma mantığında kullanılabilmelidir.
İstemcilerin düz yazı ayrıştırmasına izin vermeyin:
if (message.includes("positive")) {
// ...
}
Bu tür bir kullanımda yalnızca hata mesajını değiştirmek bile bozucu API değişikliğine dönüşür.
İnsan mesajları
İnsan mesajları geliştirilebilir ve günlükleri okuyan geliştiriciler için yazılmalıdır. Neyin başarısız olduğunu ve nasıl düzeltileceğini açıklayın:
- Kötü:
"geçersiz miktar" - İyi:
"miktar, küçük birimlerde pozitif bir tamsayı olmalıdır"
Yerelleştirme yapıyorsanız mesajı yerelleştirin; hata kodunu değiştirmeyin.
Bu ayrım, API tüketicilerinin artık otonom ajanları da içermesi nedeniyle daha da önemlidir. Yapılandırılmış ve kendi kendini açıklayan hata yanıtları, LLM tabanlı istemcilerin kurtarma davranışını iyileştirir. Bu konu yapay zeka ajanları için API hata tasarımı rehberinde ele alınıyor.
Hata yanıtında asla bulunmaması gerekenler
Hatalar, saldırganlar için önemli bir keşif kanalıdır. Hata ara katman yazılımınız aşağıdaki bilgilerin istemciye ulaşmasını engellemelidir:
- Yığın izleri, sınıf adları veya dosya yolları
- Ham SQL, sorgu parçacıkları veya ORM hataları
- Dahili ana bilgisayar adları, IP adresleri, bağlantı noktaları veya hizmet adları
- Kütüphane sürümleri ve çerçeve afiş dizeleri
- İstisna metnine gömülü sırlar, belirteçler veya bağlantı dizeleri
- Kullanıcı hesabının var olup olmadığı
Özellikle giriş ve parola sıfırlama akışlarında hata mesajlarını simetrik tutun. Bir hesabın varlığını doğrulamak kullanıcı enumerasyonuna yol açabilir.
Önerilen desen:
- Sınırdaki tüm beklenmeyen hataları yakalayın.
- Tam istisnayı sunucu tarafında bir istek kimliğiyle günlüğe kaydedin.
- İstemciye genel bir Problem Details gövdesi döndürün.
{
"detail": "Dahili bir hata oluştu",
"request_id": "req_51ad0"
}
İstemci yalnızca genel mesajı alır; günlükleriniz gerçek hatayı kaydeder ve destek ekibi iki kaydı request_id ile eşleştirebilir.
Hataları yeniden denenebilir veya terminal olarak işaretleyin
Her hata, istemcinin şu sorusunu yanıtlamalıdır:
Bu isteği tekrar denemeli miyim?
Varsayılan HTTP semantiği genellikle şu şekildedir:
-
429,502,503,504: Üstel geri çekilme ve gecikmeyle yeniden denenebilir -
500: Dikkatli bir yeniden denemeye değer olabilir - Diğer
4xxyanıtları: Aynı istekle terminal kabul edilmelidir
Retry-After varsa istemciler bu değere uymalıdır.
Zaman aşımı hataları ayrıca ele alınmalıdır. İstemci vazgeçtikten sonra istek sunucuda başarıyla tamamlanmış olabilir. Değişiklik yapan uç noktaların idempotency anahtarlarını kabul etmesi, yeniden denenen bir ödemenin iki kez ücretlendirilmesini veya kaynağın iki kez oluşturulmasını önler.
Yeniden denenebilirliği açık bir uzantı alanıyla belirtebilirsiniz:
{
"type": "https://api.example.com/problems/rate-limited",
"title": "Çok fazla istek",
"status": 429,
"code": "RATE_LIMITED",
"retryable": true,
"retry_after_seconds": 30
}
Açık retryable alanı, varsayılanları gerektiğinde geçersiz kılmanıza olanak tanır. Örneğin bazı 500 alt kodları, yeniden denemenin durumu daha da kötüleştireceği için terminal olarak işaretlenebilir.
Bu alanı bir kez belgeleyin ve tüm istemci SDK'larının aynı geri çekilme davranışını uygulamasını sağlayın.
Korelasyon kimlikleri ve hata sözleşmesi sürümleme
İki küçük karar, hata sözleşmesini tamamlar. İkisini şimdi uygulamak ileride önemli miktarda zaman kazandırır.
Her isteğe kimlik verin
- Gelen
X-Request-Idbaşlığını kabul edin veya bir kimlik oluşturun. - Her günlük satırına bu kimliği ekleyin.
- Her hata gövdesinde
request_idolarak yansıtın. - Dağıtık sistemlerde isteği hizmetler arasında izlemek için W3C
traceparentbaşlığını da kullanın.
Bir müşteri destek biletine hata yanıtını yapıştırdığında, request_id saatler süren günlük araştırmasını tek bir sorguya dönüştürebilir.
Hata sözleşmesini API gibi sürümleyin
Genellikle güvenli değişiklikler:
- Yeni bir uzantı alanı eklemek
- Yeni bir hata kodu eklemek
Bozucu değişiklikler:
-
errors[].fieldalanını yeniden adlandırmak - Bir hata kodunun anlamını değiştirmek
- Özel hata şeklinden Problem Details'e geçmek
type URI'leri, geriye dönük uyumluluk için temiz bir mekanizma sağlar:
- Eski tür URI'lerini kararlı tutun.
- Yeni anlamlar için yeni URI'ler tanımlayın.
- İstemcilerin bilinmeyen uzantı alanlarını ve kodlarını yok sayması gerektiğini belgeleyin.
Bu yaklaşım, her değişiklikte v2 yayınlamadan sözleşmeyi geliştirmenizi sağlar.
Apidog'da her hata yolunu test edin
Hata sözleşmeleri, kullanılmadıkları için zamanla bozulur. Başarılı yol her demoda çalışır; 422 dalı ise ilk müşteri ona ulaştığında kırılır.
Çözüm, başarısızlık durumlarını test süitinde birinci sınıf vatandaş yapmaktır. Apidog bu süreçte iki özellikle yardımcı olur.
Sunucu tarafı test senaryoları
Her uç nokta ve her başarısızlık durumu için bir senaryo oluşturun:
- Eksik kimlik doğrulama →
401 - Yetersiz rol →
403 - Negatif miktar →
422 -
errors[0].code→AMOUNT_NOT_POSITIVE - Ani trafik →
429veRetry-After
Apidog'un görsel iddialarıyla durum kodlarını, başlıkları ve gövde alanlarını betik yazmadan kontrol edebilirsiniz. Tüm yanıtı Problem Details JSON Şemanıza göre doğrulayarak hata şeklindeki kaymaların üretimde değil CI'da yakalanmasını sağlayabilirsiniz.
Daha fazla örnek için API iddiaları rehberine bakın.
İstemci tarafı sahte sunucuları
Ön uç ve SDK ekipleri, arka uç hazır olmadan 4xx ve 5xx yanıtlarını test edebilmelidir. Apidog sahte sunucuları, API spesifikasyonunuzdaki Problem Details gövdelerini döndürür.
Böylece aşağıdaki senaryoları simüle edebilirsiniz:
-
Retry-After: 120içeren503 - Yinelenen gönderimde
409 - Tam bir
errors[]doğrulama yanıtı
Ardından istemcinin hatayı nasıl işlediğini ve yeniden denediğini doğrulayabilirsiniz. El yapımı Express taslaklarına veya hata üretmek için arka uç kodunu geçici olarak değiştirmeye gerek kalmaz.
Hata sözleşmesini tasarlayın, senaryolar ve sahte yanıtlarla kodlayın ve ikisini de CI'ya bağlayın. Apidog'u indirin ve ücretsiz deneyin; mevcut bir OpenAPI spesifikasyonunu içe aktararak birkaç dakika içinde sahte hata yanıtları oluşturabilirsiniz.
Sıkça Sorulan Sorular
Doğrulama hataları için 400 mü, 422 mi kullanmalıyım?
İstek hatalı biçimlendirilmişse ve sunucu isteği anlayamıyorsa 400 kullanın:
- Geçersiz JSON
- Yanlış içerik türü
- Eksik zorunlu alan
İstek düzgün ayrıştırılıyor ancak değerler alan kurallarını ihlal ediyorsa 422 kullanın. Örneğin:
- Negatif ödeme miktarı
- Desteklenmeyen para birimi
Pratik ayrım şöyledir:
-
400: “İstek biçiminizi düzeltin.” -
422: “Verilerinizi düzeltin.”
Hangi yaklaşımı seçerseniz seçin, tüm uç noktalarda tutarlı uygulayın.
application/problem+json nedir?
application/problem+json, RFC 9457 tarafından Problem Details için tanımlanan medya türüdür. HTTP API'leri için standart JSON hata biçimini sağlar.
Bu içerik türüne sahip bir yanıt; type, title, status, detail ve instance alanlarını, ayrıca alan düzeyinde doğrulama hataları için errors[] gibi özel uzantıları taşıyabilir. Kayıtlı medya türünü kullanmak, genel istemcilerin ve ara katman yazılımların özel yapılandırma olmadan hataları tanımasına yardımcı olur.
İstemciler hangi HTTP hatalarını otomatik olarak yeniden denemelidir?
429, 502, 503 ve 504 yanıtlarını üstel geri çekilme ve uygun gecikmeyle yeniden deneyin. Retry-After mevcutsa bu değere uyun.
500 yanıtı dikkatli bir yeniden denemeye değer olabilir. Diğer 4xx yanıtlarını yeniden denemeyin; istek büyük olasılıkla aynı şekilde başarısız olacaktır.
Değişiklik yapan uç noktalarda yeniden denemeleri idempotency anahtarlarıyla eşleştirin. Böylece bir istek iki kez ücretlendirilmez veya iki kez kaynak oluşturmaz.
Arka ucu bozmadan API hata yanıtlarını nasıl test ederim?
Hataları simüle edin:
- İstemciyi spesifikasyonunuzdan gerçek 4xx ve 5xx gövdelerini döndüren bir Apidog sahte sunucusuna yönlendirin.
- Her hata için istemci işleme ve yeniden deneme davranışını doğrulayın.
- Sunucu tarafında geçersiz yükler, eksik kimlik doğrulama ve ani trafik için test senaryoları yazın.
- Durum kodlarını, başlıkları ve hata gövdesi şemasını doğrulayın.
- Her iki test grubunu CI'da çalıştırın.
Böylece kimsenin elle hata üretmesine gerek kalmadan hata sözleşmeniz güncel kalır.
Top comments (0)