API Response Standartları: Problem Details (RFC 7807 / RFC 9457)
HTTP API'lerinde bir hata oluştuğunda, istemciye sadece 404 Not Found veya 500 Internal Server Error gibi bir durum kodu dönmek yeterli değildir. İstemcinin, hatanın ne olduğunu, neden oluştuğunu ve nasıl düzeltilebileceğini anlaması gerekir. İşte Problem Details, HTTP API'leri için makine tarafından okunabilir (machine-readable) hata yanıtları tanımlayan bir spesifikasyondur .
1. RFC 7807 ve RFC 9457: Tarihsel Gelişim
Problem Details spesifikasyonu ilk olarak RFC 7807 (Mart 2016) ile tanımlanmıştır . Temmuz 2023'te ise RFC 9457 bu spesifikasyonun halefi olarak yayınlanmış ve RFC 7807'yi geçersiz kılmıştır .
RFC 9457'nin Getirdiği Yenilikler:
-
IANA Problem Types Registry: Yaygın kullanılan problem tipleri için merkezi bir kayıt defteri oluşturulmuştur .
-
Çoklu Problem Desteği: Tek bir yanıtta birden fazla problemi ifade etme konusunda daha net rehberlik sağlanmıştır .
-
Geriye Dönük Uyumluluk: RFC 9457, RFC 7807 ile %100 geriye dönük uyumludur. Aynı alanlar (
type,title,status,detail,instance) ve aynı medya tipi (application/problem+json) korunmuştur .
Önemli Not: RFC 9457, RFC 7807'yi geçersiz kılmış olsa da, mevcut uygulamaların değiştirilmesi zorunlu değildir. Yeni projelerde RFC 9457 referans alınmalı, mevcut projelerde ise gerektiğinde güncellenmelidir .
2. Problem Details Nesnesinin Üyeleri
Problem Details nesnesi, aşağıdaki beş temel üyeden oluşur (tümü isteğe bağlıdır) :
| Üye | Tip | Açıklama |
|---|---|---|
type |
URI | Problemin tipini tanımlayan benzersiz bir URI. Belirtilmezse varsayılan değeri about:blank'tır . |
title |
String | Problemin kısa, insan tarafından okunabilir özeti. type ile aynı olduğunda tutarlı olmalıdır . |
status |
Integer | HTTP durum kodu (ör. 403, 404, 500). Sadece bilgilendirme amaçlıdır; asıl durum kodu HTTP yanıt başlığındadır . |
detail |
String | Bu spesifik problem oluşumu için insan tarafından okunabilir açıklama. İstemcinin problemi düzeltmesine yardımcı olmalıdır . |
instance |
URI | Bu spesifik problem oluşumunu tanımlayan URI. Destek veya adli inceleme için kullanışlıdır . |
Örnek Problem Details JSON Yanıtı:
json
{
"type": "https://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"status": 403,
"detail": "Your current balance is 30, but that costs 50.",
"instance": "/account/12345/msgs/abc",
"balance": 30,
"accounts": ["/account/12345", "/account/67890"]
}
Bu örnekte balance ve accounts gibi genişletme üyeleri (extension members) eklenmiştir. Problem Details spesifikasyonu, problem tipine özel ek alanların eklenmesine izin verir .
3. RFC 9457: about:blank Varsayılan Tipi
RFC 9457, about:blank URI'sini varsayılan problem tipi olarak tanımlar . Bir Problem Details nesnesi type üyesi içermiyorsa, bu URI kullanılmış sayılır. about:blank kullanıldığında, title üyesinin HTTP durum kodunun önerilen ifadesiyle aynı olması önerilir (ör. 404 için "Not Found") .
4. ASP.NET Core'da Problem Details Uygulaması
ASP.NET Core, Problem Details'i yerleşik olarak destekler ve AddProblemDetails() metodu ile kolayca etkinleştirilebilir .
Temel Yapılandırma:
csharp
var builder = WebApplication.CreateBuilder(args); // Problem Details servislerini ekle builder.Services.AddProblemDetails(); var app = builder.Build(); // Global hata yakalama middleware'ini ekle app.UseExceptionHandler(); app.UseStatusCodePages(); app.Run();
Özel Problem Details Üretme (Lambda ile):
csharp
app.UseExceptionHandler(exceptionHandlerApp =>
{
exceptionHandlerApp.Run(async context =>
{
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
var exceptionFeature = context.Features.Get<IExceptionHandlerFeature>();
var exception = exceptionFeature?.Error;
await context.Response.WriteAsJsonAsync(new ProblemDetails
{
Type = "https://example.com/probs/internal-error",
Title = "Internal Server Error",
Status = StatusCodes.Status500InternalServerError,
Detail = exception?.Message,
Instance = context.Request.Path
});
});
});
ProblemDetails Özelleştirme (.NET 8+):
csharp
builder.Services.AddProblemDetails(options =>
{
options.CustomizeProblemDetails = ctx =>
{
// Tüm ProblemDetails yanıtlarına trace ID ekle
ctx.ProblemDetails.Extensions["traceId"] = ctx.HttpContext.TraceIdentifier;
// Hata tipine göre özelleştirme
if (ctx.ProblemDetails.Status == 409)
{
ctx.ProblemDetails.Title = "Conflict";
}
};
});
Bu yaklaşım, tüm Problem Details yanıtlarına tutarlı ek alanlar eklemek için idealdir .
Minimal API'lerde Problem Details:
.NET 9 ile birlikte, ProducesProblem ve ProducesValidationProblem uzantı metotları, rota gruplarında (route groups) kullanılabilir hale gelmiştir .
5. ValidationProblemDetails: Doğrulama Hataları için Özel Format
ASP.NET Core, doğrulama hataları için ValidationProblemDetails sınıfını sunar. Bu sınıf, ProblemDetails'i genişleterek errors adında bir sözlük (dictionary) ekler .
Örnek ValidationProblemDetails Yanıtı:
json
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"age": ["The field age must be a positive integer."],
"color": ["The field color must be 'green', 'red' or 'blue'."]
}
}
6. En İyi Pratikler
-
Tutarlılık: Tüm API hata yanıtlarında Problem Details formatını kullanın.
-
typeURI'lerini Dokümante Edin: Her problem tipi için anlamlı ve kalıcı URI'ler tanımlayın.typeURI'si, insan tarafından okunabilir dokümantasyona işaret etmelidir . -
Güvenlik: Hata yanıtlarında hassas bilgileri (stack trace, iç sistem detayları) paylaşmayın.
detailalanı, istemcinin problemi düzeltmesine yardımcı olacak bilgiler içermelidir, hata ayıklama bilgisi değil . -
Genişletme Alanlarını Kullanın: Problem tipine özel ek bilgiler için
extensionssözlüğünü kullanın . -
Medya Tipi: Yanıtın
Content-Typebaşlığınıapplication/problem+jsonolarak ayarlayın .
Sonuç
Problem Details (RFC 9457 / RFC 7807), HTTP API'lerinde hata yanıtlarını standartlaştırmak için endüstri standardı haline gelmiştir. Beş temel üye (type, title, status, detail, instance) ve genişletme alanları ile makine tarafından okunabilir, tutarlı ve bilgilendirici hata yanıtları oluşturmanıza olanak tanır. ASP.NET Core, AddProblemDetails() ve IProblemDetailsService ile bu spesifikasyonu yerleşik olarak destekler. RFC 9457, RFC 7807 ile geriye dönük uyumlu olduğu için mevcut uygulamaların değiştirilmesi gerekmez; ancak yeni projelerde RFC 9457 referans alınmalıdır.