DEV Community

Cover image for REST API Hata Yönetimi En İyi Uygulamaları: Durum Kodları, RFC 9457 ve Yeniden Denenebilir Hatalar
Tobias Hoffmann
Tobias Hoffmann

Posted on Originally published at apidog.com

REST API Hata Yönetimi En İyi Uygulamaları: Durum Kodları, RFC 9457 ve Yeniden Denenebilir Hatalar

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.

Apidog'u bugün deneyin

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:

  1. 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.
  2. 429 yanıtında Retry-After olmaması 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" }
Enter fullscreen mode Exit fullscreen mode
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"
}
Enter fullscreen mode Exit fullscreen mode

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")) {
  // ...
}
Enter fullscreen mode Exit fullscreen mode

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:

  1. Sınırdaki tüm beklenmeyen hataları yakalayın.
  2. Tam istisnayı sunucu tarafında bir istek kimliğiyle günlüğe kaydedin.
  3. İstemciye genel bir Problem Details gövdesi döndürün.
{
  "detail": "Dahili bir hata oluştu",
  "request_id": "req_51ad0"
}
Enter fullscreen mode Exit fullscreen mode

İ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 4xx yanı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
}
Enter fullscreen mode Exit fullscreen mode

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-Id baş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_id olarak yansıtın.
  • Dağıtık sistemlerde isteği hizmetler arasında izlemek için W3C traceparent baş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[].field alanı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].codeAMOUNT_NOT_POSITIVE
  • Ani trafik → 429 ve Retry-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: 120 içeren 503
  • 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:

  1. İstemciyi spesifikasyonunuzdan gerçek 4xx ve 5xx gövdelerini döndüren bir Apidog sahte sunucusuna yönlendirin.
  2. Her hata için istemci işleme ve yeniden deneme davranışını doğrulayın.
  3. Sunucu tarafında geçersiz yükler, eksik kimlik doğrulama ve ani trafik için test senaryoları yazın.
  4. Durum kodlarını, başlıkları ve hata gövdesi şemasını doğrulayın.
  5. 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.

Referanslar

Top comments (0)