API Tasarımı & Hata Yönetimi 4 dk okuma 10 okunma

Problem Details: RFC 9457 / 7807

HTTP API'lerinde hata yanıtlarını standart bir formata kavuşturan Problem Details spesifikasyonu (RFC 7807 ve halefi RFC 9457), beş temel üye (type, title, status, detail, instance), genişletme alanları, medya tipi (application/problem+json), .NET/ASP.NET Core'da AddProblemDetails ve IProblemDetailsService ile uygulama yöntemleri ve en iyi pratikler ele alınır.

Problem Details: RFC 9457 / 7807

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

  1. Tutarlılık: Tüm API hata yanıtlarında Problem Details formatını kullanın.

  2. type URI'lerini Dokümante Edin: Her problem tipi için anlamlı ve kalıcı URI'ler tanımlayın. type URI'si, insan tarafından okunabilir dokümantasyona işaret etmelidir .

  3. Güvenlik: Hata yanıtlarında hassas bilgileri (stack trace, iç sistem detayları) paylaşmayın. detail alanı, istemcinin problemi düzeltmesine yardımcı olacak bilgiler içermelidir, hata ayıklama bilgisi değil .

  4. Genişletme Alanlarını Kullanın: Problem tipine özel ek bilgiler için extensions sözlüğünü kullanın .

  5. Medya Tipi: Yanıtın Content-Type başlığını application/problem+json olarak 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.

Tüm yazılar Soru ya da yorumun mu var? Yaz