API hata gövdelerimi RFC 7807 problem+json biçimine mi taşımalıyım?
Soru
Bir platformumuz var ve içindeki her servis (bazıları Laravel, bazıları Go) hataları biraz farklı bir gövdeyle dönüyor: birinde `{"error": "..."}`, ötekinde `{"message": "...", "code": 42}`, bir başkasında iç içe bir `errors` objesi. İstemci tarafındaki ekipler her servisin hatasını ayrı ayrı parse etmek zorunda kalıyor ve bu sürdürülemez hale geldi. Hata gövdelerini RFC 7807 `application/problem+json` biçimine taşıyarak tek tip bir sözleşme kursam mantıklı olur mu, yoksa gereksiz bir standart yükü mü getirir?
Cevap
Kısa cevap: Evet, standartlaştırın.
Kısa cevap
Ama iki şart: 7807 yerine onu güncelleyen (obsolete eden) RFC 9457’yi baz alın ve bunu her endpoint’e elle değil, tek bir merkezi katmanda zorunlu kılın.
Neden
-
7807 artık RFC 9457. Aynı şekil, 2023’te güncellendi. Yeni işlerde 9457’yi referans alın. Alanlar aynı:
type(URI),title,status,detail,instance— ve istediğiniz kadar ekstra (extension) alan koyabilirsiniz. -
Asıl kazanç alan isimleri değil, tek tip zarftır. İstemci ekipleri artık her serviste tek bir şekli parse eder. Sizin derdiniz zaten tam olarak buydu; standardın bütün değeri de burada. Yani evet, yapmaya değer.
Ne yapmalı
-
Content-Type’ı doğru set edin: application/problem+json. İstemciler ve ara proxy’ler bunu normal bir gövdeden ayırt edebilsin. Bu başlığı unutmak, standardı yarım uygulamaktır.
-
type stabil bir makine anahtarıdır — sözleşme gibi davranın. Bir URN ya da bir dokümantasyon URL’i kullanın. İstemci
title/detailgibi insan-okunur alanlara değil,type’a göre dallanır.detailiçine stack trace veya iç ayrıntı sızdırmayın; orası kullanıcıya dönük insan-okunur bir cümledir.{ "type": "https://api.example.com/problems/insufficient-funds", "title": "Insufficient funds", "status": 422, "detail": "Cüzdan 7f3a bakiyesi 12.00, gereken 50.00.", "instance": "/wallets/7f3a/withdrawals/9910" } -
Tek yerde zorunlu kılın — exception handler / middleware. Laravel’de (11’den beri
bootstrap/app.phpiçindekiwithExceptions()->render(), öncesindeHandler’ınrenderkatmanı), Go’da merkezi bir “error → problem” mapper’da üretin. Her endpoint’te ayrı ayrı yazarsanız zamanla drift başlar; standardın anlamı da kaçar. -
Validation hataları için extension gerekir. 9457 alan-bazlı hata listesi tanımlamaz. Doğrulama için bir
errorsdizisi extension’ı ekleyin ve bu şekli bir kez tüm servislerde sabitleyin — yoksa yine servis başına farklılaşır. -
Geçişi geriye dönük uyumlu planlayın. Mevcut istemciler eski gövdeyi bekliyor olabilir. Sunucu tarafında yeni biçime geçmek kolay ama istemciler bir gecede güncellenmez. Yeni
problem+jsonbiçimini bir API sürümüne bağlayın ya da geçiş penceresinde her iki alanı da (örneğin eskimessageile yenidetail) bir süre birlikte döndürün; istemciler taşındıkça eskisini kaldırın. -
Her şeyi standarda boğmayın. problem+json hata gövdeleri içindir; başarılı yanıtların şeklini değiştirmez. Ayrıca dokümantasyonu da otomatikleştirin: OpenAPI şemanızda
typekataloğunu referans olarak tanımlayın ki istemciler hangi hata tiplerini bekleyeceklerini sözleşmeden görsün.
Sonuç: Ben olsam 9457’yi baz alır, type için versiyonlanabilir bir URI şeması belirler, üretimi tek bir exception handler’a toplar ve validation için ortak bir errors extension’ı tanımlardım. Migrasyonu da tek seferde değil, type kataloğunu doldururken ve istemcileri taşırken kademeli yapardım. Standardın değeri disiplinde: tek zarf, tek üretim noktası, type’ı sözleşme gibi yönetmek.
İlgili Yazılar
Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.