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 tasarlar ve hataların çerçevenin varsayılan olarak ne yaparsa yapsın ortaya çıkmasına izin verir. İşte böylece bir API'de üç farklı hata şekliyle, "success": false içeren 200 yanıtıyla ve veritabanı şemanızı herkese açık internete sızdıran bir yığın iziyle karşılaşırsınız.
Bu rehber, REST hizmetleri için uçtan uca API hata yönetiminin en iyi uygulamalarını kapsar: doğru durum kodunu seçmek, RFC 9457 Problem Details ile tek bir hata gövdesinde standardizasyon sağlamak, makine tarafından okunabilir kodları insan mesajlarından ayırmak, hataları yeniden denenebilir olarak işaretlemek ve sırları yanıtlardan uzak tutmak. Bu, REST API'lerinin hangi HTTP durum kodlarını kullanması gerektiği üzerine yaptığımız ayrıntılı incelemeye dayanır ve rehberin açık bıraktığı sözleşme düzeyindeki kararları ekler. Ayrıca, Apidog'da her bir hata yolunu nasıl test edeceğinizi de göreceksiniz, çünkü test etmediğiniz bir hata sözleşmesi, sahip olmadığınız bir sözleşmedir.
Gövdeyle değil, durum koduyla başlayın
HTTP size zaten ücretsiz olarak ilk katman hata semantiği sunar. RFC 9110 durum kodu ailelerini tanımlar: 4xx, istemcinin yanlış bir şey yaptığını ve aynı isteği tekrarlamanın tekrar başarısız olacağını; 5xx ise sunucunun başarısız olduğunu ve istemcinin isteğinin doğru olabileceğini belirtir. Tek bir hata gövdesi yazmadan önce bu ayrımı doğru yapın, çünkü genel istemciler, proxy'ler, önbellekler ve yeniden deneme kütüphaneleri, JSON'unuzu hiç okumadan buna göre dallanır.
En yaygın hatalar, birbirine benzeyen birkaç çift etrafında toplanır. Tasarım yaparken MDN'nin HTTP durum kodu referansını açık tutun ve ekipleri zorlayan kodlar için bu karar tablosunu kullanın.
| Durum | Kullan | Değil | Neden |
|---|---|---|---|
| Hatalı istek: bozuk JSON, yanlış içerik türü, eksik zorunlu alan | 400 Hatalı İstek | 422 | Sunucu isteği hiç ayrıştıramıyor veya anlayamıyor |
| Anlamsal kuralları ihlal eden, iyi biçimlendirilmiş istek: miktar negatif, para birimi desteklenmiyor | 422 İşlenemeyen İçerik | 400 | Sözdizimi iyi; değerler değil |
| Kimlik bilgisi yok veya süresi dolmuş/geçersiz belirteç | 401 Yetkilendirilmemiş | 403 | İstemci kim olduğunu kanıtlamadı. WWW-Authenticate gönderin |
| Geçerli kimlik bilgileri, yetersiz izinler | 403 Yasak | 401 | Kimlik biliniyor; erişim reddedildi. Yeniden kimlik doğrulama yardımcı olmaz |
| Kaynak hiç var olmadı veya var olduğunu doğrulamayacaksınız | 404 Bulunamadı | 410 | Güvenli varsayılan; ayrıca kaynakları yetkisiz araştırmalardan gizler |
| Kaynak vardı ve kasıtlı, kalıcı olarak kaldırıldı | 410 Kaldırıldı | 404 | İstemcilere ve tarayıcılara referanslarını silmelerini söyler |
| Durum çakışması: yinelenen anahtar, eski sürüm, düzenleme çakışması | 409 Çakışma | 400 | İstek geçerli ancak mevcut kaynak durumuyla çakışıyor |
| İstemci bir hız limitini aştı | 429 Çok Fazla İstek | 503 | İstemcilerin doğru şekilde geri çekilmesi için daima Retry-After ekleyin |
| Kodunuzda işlenmemiş istisna | 500 Dahili Sunucu Hatası | 502 | Sunucunuz bozuldu |
| Yukarı akış hizmeti ağ geçidinize çöp döndürdü | 502 Hatalı Ağ Geçidi | 500 | Hata uçta değil, uçtan sonraki aşağı akıştadır |
| Sunucu aşırı yüklü veya bakımda | 503 Hizmet Kullanılamıyor | 500 | Tanım gereği geçicidir; mümkünse Retry-After ekleyin |
| Yukarı akış hizmetinin süresi doldu | 504 Ağ Geçidi Zaman Aşımı | 500 | "Yavaş bağımlılık" ile "bozuk kod"u ayırt eder |
Bunlardan ikisi ekstra vurguyu hak ediyor. Birincisi, 401 ile 403 arasındaki ayrım bir güvenlik sınırıdır, bir stil seçimi değildir: kimliği doğrulanmamış bir arayana 403 döndürmek, kaynağın var olduğu gerçeğini sızdırır. İkincisi, Retry-After olmadan 429, istemcileri sıkı döngülerde size saldırmaya teşvik eder. Eğer hız limitiniz varsa ve olmalı, durumu somut bir geri çekilme sinyaliyle eşleştirin; API hız limitlendirme rehberimiz başlık matematiğini ve arkasındaki algoritmaları kapsar.
Tek hata gövde şekli: RFC 9457 Problem Details
Durum kodu doğru olduğunda, API'nizin döndürdüğü her hata tek bir medya türünü ve tek bir şemayı paylaşmalıdır. Standart cevap, application/problem+json olarak sunulan RFC 9457 Problem Details'tir. Beş temel üyeyi tanımlar: type (hata kategorisini tanımlayan bir URI), title (kısa bir insan özeti), status (kolaylık sağlamak için tekrarlanan HTTP kodu), detail (bu olayda neyin yanlış gittiği) ve instance (bu özel başarısızlık için bir URI). Diğer her şey, kendinizin tanımladığı uzantı üyelerine gider.
Burada spesifikasyonu yeniden türetmeyeceğiz; RFC 9457 açıklayıcımız her üyeyi, kayıt kurallarını ve RFC 7807'nin yerini nasıl aldığını ayrıntılarıyla anlatır. Sözleşmeniz için önemli olan kalıptır: standart zarf, özel uzantılar. İşte bir ödeme uç noktasındaki 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[] dizisi bir uzantı üyesidir ve istemcilerin en çok sevdiği şey budur: bir ön uçun her hatayı tek bir belirsiz afiş göstermek yerine tam form alanına eşlemesine olanak tanır. Alan yollarını istikrarlı bir biçimde tutun (JSON Pointer veya noktalı yollar, birini seçin), böylece istemci kodu bunları programatik olarak bağlayabilir.
Bir kural size en çok acıyı kurtarır: çerçevenizin veya ağ geçidinizin oluşturduğu hatalar da dahil olmak üzere her hata için bu şekli döndürün. İşleyicilerinizden Problem Details, ancak yük dengeleyicinizin 502 sayfasından HTML alan bir istemcinin hala iki ayrıştırıcı yazması gerekir.
Makine tarafından okunabilir kodlar ve insan mesajları
Örnekte hem code hem de message alanlarının bulunduğunu fark edin. Bu bilinçlidir. Farklı kitlelere hizmet ederler ve asla tek bir dizgeye indirgenmemelidirler.
Makine tarafından okunabilir kodlar (AMOUNT_NOT_POSITIVE, CURRENCY_UNSUPPORTED, IDEMPOTENCY_KEY_REUSED) sözleşmedir. İstemciler bunlara göre dallandığından, kararlı, belgelenmiş ve numaralandırılabilir olmaları gerekir. Müşterilerin asla düzyazı ayrıştırmasını sağlamayın; biri if (message.includes("positive")) yazdığı an, metin düzenlemeniz bozucu bir değişikliğe dönüşür.
İnsan mesajları tam tersidir: herhangi bir zamanda geliştirilebilir, günlükleri okuyan bir geliştirici için yazılmıştır ve asla yük taşıyıcı değildir. Ne başarısız oldu ve düzeltmesi neye benziyor belirtin: "miktar, küçük birimlerde pozitif bir tamsayı olmalıdır" ifadesi "geçersiz miktar" ifadesinden daha iyidir. Yerelleştiriyorsanız, mesajı yerelleştirin ve kodu olduğu gibi bırakın.
Bu ayrım, API tüketicilerinin artık otonom ajanları da içermesiyle daha da önem kazanmaktadır. LLM tabanlı istemciler, yapılandırılmış, kendi kendini açıklayan hatalardan çok daha iyi kurtulur; bu açıyı yapay zeka ajanları için API hata tasarımı bölümünde ele alıyoruz.
Bir hata yanıtında asla bulunmaması gerekenler
Hata yanıtları, saldırganlar için favori bir keşif kanalıdır, çünkü işlenmeyen hatalar genellikle çok konuşkandır. Hata ara katman yazılımınız, aşağıdakilerden hiçbirinin bir istemciye ulaşmamasını garanti etmelidir:
- Yığın izleri, sınıf adları veya dosya yolları
- Ham SQL, sorgu parçacıkları veya ORM hataları
- Dahili ana bilgisayar adları, IP'ler, 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ığı (giriş ve parola sıfırlama akışlarında, hataları simetrik tutun)
Desen basittir: sınırdaki her şeyi yakalayın, tam istisnayı sunucu tarafında bir istek kimliğiyle birlikte günlüğe kaydedin ve aynı kimlikle genel bir Problem Detayları gövdesi döndürün. İstemci "detail": "Dahili bir hata oluştu", "request_id": "req_51ad0" alır, günlükleriniz gerçeği kaydeder ve destek ikisini birleştirebilir.
Hataları yeniden denenebilir veya terminal olarak işaretle
Döndürdüğünüz her hata, istemcinin sormak üzere olduğu bir soruyu yanıtlar: bunu tekrar denemeli miyim? Cevabı, her istemci ekibinin tahmin etmesini bırakmak yerine sözleşmeye ekleyin.
Durum kodları varsayılan semantiği taşır. 429, 502, 503 ve 504 üstel geri çekilme ve gecikmeyle birlikte yeniden denenebilir. 500 belirsizdir ancak genellikle bir dikkatli yeniden denemeye değer. Diğer tüm 4xx kodları terminaldir: aynı istekle 401, 403, 404 veya 422'yi yeniden denemek kotayı boşa harcar ve günlükleri kirletir. Zaman aşımları kendi dikkatlerini hak eder, çünkü istemci vazgeçtikten sonra istek başarılı olmuş olabilir; bu klasik 408 istek zaman aşımı sorunudur ve bu yüzden değişen uç noktaların idempotentlik anahtarlarını kabul etmesi gerekir, böylece yeniden denenen bir ödeme iki kez ücretlendirme yapamaz.
Bir uzantı üyesiyle yeniden denenebilirliği açıkça 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 bir retryable bayrağı, varsayılanları gerektiğinde geçersiz kılmanıza olanak tanır, örneğin belirli bir 500 alt kodunu terminal olarak işaretlemek gibi, çünkü yeniden denemek durumu bozabilir. Bayrağı bir kez belgeleyin ve gönderdiğiniz her istemci SDK'sı tek tip geri çekilme davranışı gösterir.
Korelasyon Kimlikleri ve Hata Sözleşmesi Sürümlendirme
İki küçük karar sözleşmeyi tamamlar ve her ikisi de şimdi ucuz, sonra pahalıdır.
Her isteğe bir kimlik verin. Gelen bir X-Request-Id başlığını kabul edin (veya bir tane oluşturun), her günlük satırına bunu damgalayın ve her hata gövdesinde request_id olarak yansıtın. Bir müşteri bir destek biletine bir hata yapıştırdığında, o tek alan bir saatlik günlük araştırmasını tek bir sorguya dönüştürür. Dağıtılmış kurulumlarda, kimliğin hizmetler arasında isteği takip etmesi için bununla birlikte bir W3C traceparent yayınlayın.
Hata sözleşmenizi API'nin kendisi gibi sürümleyin. Yeni bir uzantı üyesi veya yeni bir hata kodu eklemek güvenlidir. errors[].field'i yeniden adlandırmak, bir kodun anlamını değiştirmek veya özel bir şekilden Problem Details'e geçmek bozucu bir değişikliktir ve ekiplerin en az test ettiği kod yollarını bozar. type URI'si size temiz bir mekanizma sunar: eski tür URI'lerini sonsuza dek kararlı tutun, yeni semantikler için yeni URI'ler tanıtın ve belgelerinizde bilinmeyen uzantı üyelerinin ve bilinmeyen kodların yok sayılması gerektiğini, hata olarak ele alınmaması gerektiğini belirtin. Bu ileriye dönük uyumluluk maddesi, v2 olmadan geliştirme yapmanızı sağlar.
Apidog'da her hata yolunu test edin
İşte rahatsız edici gerçek: hiçbir şey onları kullanmadığı için hata sözleşmeleri çürür. Başarılı yol her demoda çalışır; 422 dalı bir müşteri ona ulaştığında çalışır. Çözüm, başarısızlık durumlarını test süitinizde birinci sınıf vatandaş yapmak ve Apidog'un iş akışındaki yerini tam da burada kazanır.
İki özellik doğrudan bu sorunla eşleşir.
Sunucu tarafı için test senaryoları. Her uç nokta için, her başarısızlık durumu için bir senaryo oluşturun: eksik kimlik doğrulama 401 bekler, yetersiz rol 403 bekler, negatif miktar errors[0].code AMOUNT_NOT_POSITIVE'a eşit olan 422 bekler, ani trafik Retry-After başlığıyla 429 bekler. Apidog'un görsel iddiaları, betikleme yapmadan durumu, başlıkları ve gövde alanlarını kontrol eder ve tüm yükü Problem Detayları JSON Şemanıza göre doğrulayabilirsiniz, böylece hata şeklindeki herhangi bir kayma üretimde değil, CI'da başarısız olur. API iddiaları rehberimiz iddia kalıplarını ayrıntılı olarak gösterir.
İstemci tarafı için sahte sunucular. Ön uç ve SDK ekiplerinizin, arka uç talep üzerine bunları üretemeden önce 4xx ve 5xx yanıtlarına karşı geliştirmeleri gerekir. Apidog sahte sunucuları, API spesifikasyonunuzdaki tam Problem Detayları gövdelerini döndürür, böylece Retry-After: 120 ile bir 503'ü, çifte gönderimde bir 409'u veya tam bir errors[] doğrulama yükünü simüle edebilir, ardından istemcinin nasıl işlediğini ve yeniden denediğini izleyebilirsiniz. El yapımı Express taslağı yok, bir hatayı zorlamak için arka uç kodunu yorum satırı yapma yok.
Hata sözleşmesini tasarlayın, senaryolar ve sahteler olarak kodlayın ve ikisini de CI'ya bağlayın. Apidog'u indirin ve ücretsiz deneyin; mevcut bir OpenAPI spesifikasyonunu içe aktarmak, birkaç dakika içinde sahte hata yanıtları elde etmenizi sağlar.
Sıkça Sorulan Sorular
Doğrulama hataları için 400 mü yoksa 422 mi kullanmalıyım?
İstek hatalı biçimlendirilmişse ve sunucu anlayamıyorsa 400 kullanın: geçersiz JSON, yanlış içerik türü, eksik zorunlu bir alan. İstek düzgün bir şekilde ayrıştırılıyorsa ancak değerler alan kurallarınızı ihlal ediyorsa, örneğin negatif bir ödeme miktarı veya desteklenmeyen bir para birimi gibi durumlarda 422 kullanın. Pratik getirisi tanısal niteliktedir: 422 istemciye "verilerinizi düzeltin" derken, 400 "istek biçiminizi düzeltin" der. Hangi ayrımı seçerseniz seçin, her uç noktada tutarlı bir şekilde uygulayın.
application/problem+json nedir?
Bu, RFC 9457 tarafından Problem Details için tanımlanan medya türüdür; HTTP API'leri için standart JSON hata biçimidir. Bu içerik türüne sahip bir yanıt, type, title, status, detail ve instance üyelerini ve ayrıca alan düzeyinde doğrulama hataları için bir errors[] dizisi gibi tanımladığınız herhangi bir uzantıyı taşır. Kayıtlı medya türünü kullanmak, genel istemcilerin ve ara katman yazılımların özel yapılandırma olmadan hatalarınızı tanımasını sağlar. RFC 9457 açıklayıcımız spesifikasyonun tamamını kapsar.
İstemciler hangi HTTP hatalarını otomatik olarak yeniden denemelidir?
429, 502, 503 ve 504'ü üstel geri çekilme ve gecikmeyle yeniden deneyin, Retry-After mevcutsa buna uyun. 500'ü dikkatli bir yeniden denemeye değer olarak kabul edin. Diğer 4xx yanıtlarını yeniden denemeyin; istek her seferinde aynı şekilde başarısız olacaktır. Değişen uç noktalar için, yeniden denemeleri idempotency anahtarlarıyla eşleştirin, böylece tekrarlanan bir istek iki kez ücretlendirme veya iki kez oluşturma yapamaz.
Arka ucu bozmadan API hata yanıtlarını nasıl test ederim?
Bunları simüle edin. İstemcinizi, spesifikasyonunuzdan tam 4xx ve 5xx gövdelerini döndüren bir Apidog sahte sunucusuna yönlendirin, ardından her birine karşı işleme ve yeniden deneme davranışını doğrulayın. Sunucu tarafında, geçersiz yükler, eksik kimlik doğrulama ve ani trafik gönderen test senaryoları yazın, ardından durum kodlarını, başlıkları ve hata gövdesi şemasını iddia edin. Her iki yarım da CI'da çalışır, böylece hata sözleşmesi, kimse elle hataları zorlamadan dürüst kalır.
