TB
← Tüm yazılar

Hata sozlesmeleri

API hata yanitlarinin standartlastirilmasi, RFC 7807 Problem Details formati ve tuketici dostu hata mesajlari oluşturma pratikleri.

API tasarımında başarı yanitlari kadar hata yanitlarinin kalitesi de istemci geliştirici deneyimini belirler. Tutarsiz hata formatlari, farklı endpoint'lerde değişen alan isimleri ve makine okunamaz mesajlar entegrasyon maliyetini artirir. Hata sozlesmesi (error contract), tüm API yuzeyinde geçerli standart bir yapı tanimlar. RFC 7807 Problem Details for HTTP APIs bu alanda endustri standardina en yakın formattir. Iyi bir hata sozlesmesi hem insan okuyucuya anlamli mesaj sunar hem de otomasyon icin kararli alanlar sağlar.

Standart hata formatinin gerekliligi

Buyuyen API'lerde onlarca servis ve yuzlerce endpoint olabilir. Her biri farklı JSON hata uretirse istemci SDK tek deserializer yazamaz, log kurallari parcalanir, destek ekipleri kod karsilastiramaz. Standart format bilinen alanlarla hatayi siniflandirir. Istemci type URI'sine gore dallanabilir, kullanıcıya detail gosterilebilir, log sistemleri status ve traceId ile gruplama yapar. Operasyon ekipleri tekrarlayan hata tiplerini alarm kurallarina baglayabilir.

RFC 7807 Problem Details yapisi

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/problem+json

{
  "type": "https://api.example.com/problems/validation-error",
  "title": "Dogrulama hatasi",
  "status": 422,
  "detail": "Bir veya daha fazla alan gecersiz.",
  "instance": "/orders/req-9f3a2",
  "errors": [
    { "field": "email", "code": "invalid_format", "message": "Gecerli e-posta girin." },
    { "field": "quantity", "code": "out_of_range", "message": "Miktar 1 ile 999 arasinda olmali." }
  ]
}

type URI'si hatayi benzersiz tanimlar ve genelde sabit kalir. title kisa özet; degistirilmemeli. detail istege özel açıklama tasir. instance hatayi tetikleyen istek yolunu gösterir. Uzantilar (extension members) domain'e özel alanlar ekler: errors, traceId, retryAfterSeconds. Medya tipi application/problem+json veya application/problem+xml olabilir.

HTTP durum kodu eslestirmesi

  1. 400 Bad Request: Genel istemci hatasi, malformed JSON, eksik header.
  2. 401 Unauthorized: Kimlik dogrulama eksik veya gecersiz token.
  3. 403 Forbidden: Kimlik var ama kaynak veya eylem icin yetki yok.
  4. 404 Not Found: Kaynak bulunamadi.
  5. 405 Method Not Allowed: Kaynak var ama metot desteklenmiyor.
  6. 409 Conflict: Catisma, duplicate kayıt, concurrency, is kurali ihlali.
  7. 422 Unprocessable Entity: Semantik dogrulama başarısız; JSON geçerli ama is kurallari saglanmiyor.
  8. 429 Too Many Requests: Rate limit asildi.
  9. 503 Service Unavailable: Geçici kesinti; retry uygun.
  10. 500 Internal Server Error: Sunucu hatasi; detay sizdirilmez.

Status kodu ile Problem Details icindeki status alani tutarlı olmalidir. Ayni hata tipi farklı endpoint'lerde ayni type URI ile donulmelidir.

Alan bazli dogrulama hatalari

Form ve komut API'lerinde yapisal hata listesi donulmelidir. field JSON Pointer veya nokta notasyonu ile tutarlı olmalidir: /shippingAddress/postalCode. code makine okunur sabit string; yerellestirme anahtari olarak kullanılır. message insan okuyabilir açıklama; Accept-Language ile degisebilir. Birden fazla hata ayni yanitta toplanir; istemci tüm alanlari tek seferde duzeltebilir. Cross-field validation (baslangic tarihi bitisten sonra) icin field null veya ust düzey path kullanılır.

Domain ve is kurali hatalari

Yetersiz stok, kredi limiti asimi, siparis durumu uyumsuzlugu gibi durumlar generic 400 yerine anlamli type URI ile 409 Conflict veya 422 donulur. Örnek: https://api.example.com/problems/insufficient-stock. Istemci bu tipe gore kullanıcıya özel mesaj veya alternatif aksiyon (bekleme listesi) sunabilir. Domain hatalari exception handler'da merkezi yakalanir; controller'da her metotta try-catch tekrari olmamali.

traceId ve gozlemlenebilirlik

{
  "type": "https://api.example.com/problems/internal-error",
  "title": "Sunucu hatasi",
  "status": 500,
  "detail": "Beklenmeyen bir hata olustu. Destek ekibine traceId ile basvurun.",
  "traceId": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
}

traceId W3C Trace Context veya OpenTelemetry span ID ile eslestirilir. Destek personeli log sisteminde ayni ID ile tam istek zincirini görür. Istemci hata raporlarinda traceId gondermelidir. Üretim ortaminda 500 yanitlarinda stack trace, ic IP veya veritabanı tablo adi gibi bilgiler sizdirilmamali.

ASP.NET Core ProblemDetails entegrasyonu

builder.Services.AddProblemDetails(options =>
{
    options.CustomizeProblemDetails = ctx =>
    {
        ctx.ProblemDetails.Extensions["traceId"] =
            Activity.Current?.Id ?? ctx.HttpContext.TraceIdentifier;
    };
});

builder.Services.AddExceptionHandler<GlobalExceptionHandler>();

ValidationException icin özel handler yazilir; FluentValidation hatalari errors dizisine map edilir. IProblemDetailsService ile Minimal API'de tutarlı yanıt uretilir. Development ortaminda detail genişletilebilir; Production'da kisitlanir.

SDK ve istemci desenleri

public class ApiException : Exception
{
    public string Type { get; init; }
    public int Status { get; init; }
    public string TraceId { get; init; }
    public IReadOnlyList<FieldError> Errors { get; init; }
}

public async Task<T> SendAsync<T>(HttpRequestMessage req, CancellationToken ct)
{
    var res = await _http.SendAsync(req, ct);
    if (res.IsSuccessStatusCode)
        return await res.Content.ReadFromJsonAsync<T>(cancellationToken: ct);
    var problem = await res.Content.ReadFromJsonAsync<ProblemDetails>(cancellationToken: ct);
    throw problem.ToApiException();
}

Retry yalnizca idempotent isteklerde ve 503/429 icin uygulanir. 400 ve 422 retry edilmemeli. SDK hata kodlarini enum veya sabit sınıf olarak export eder.

Güvenlik ve bilgi sizintisi

404 vs 403 politikasi dokumante edilmeli: kaynak varligini sizdirmamak icin yetkisiz erisimde 404 tercih edilebilir (security through obscurity degil, bilincli politika). Authentication ve authorization hatalari ayri status ile donulmeli. Rate limit 429 ile Retry-After header birlikte kullanılır. Problem Details govdesinde ic servis adlari veya SQL fragmentleri yer almamali.

Rate limit, Retry-After ve uzantilar

429 yanitinda Retry-After header istemci backoff algoritmasini yonlendirir. Problem Details govdesinde retryAfterSeconds uzantisi SDK kolayligi sağlar. Quota asiminda type URI ayri tanimlanir: quota-exceeded. Istemci SDK exponential backoff ile jitter uygular.

Çoklu dil destegi

Accept-Language header'ina gore detail ve alan message degerleri yerellestirilebilir. type ve code sabit kalir; çeviri dosyalari bu anahtarlara baglanir. Eksik çeviri durumunda varsayilan dil (genelde Ingilizce) kullanılır.

Hata katalogu ve OpenAPI

Her type URI icin dokumantasyon sayfasi: açıklama, olasi nedenler, istemci aksiyonu, örnek yanıt. OpenAPI responses bolumunde her endpoint icin 4xx/5xx semalari Problem Details referansi ile tanimlanir. Örnek:

responses:
  '422':
    description: Dogrulama hatasi
    content:
      application/problem+json:
        schema:
          $ref: '#/components/schemas/ValidationProblem'

GraphQL ve gRPC karsilastirmasi

REST Problem Details HTTP odaklidir. GraphQL hatalari errors dizisinde extensions ile genisletilir; partial success mumkundur. gRPC google.rpc.Status ve BadRequest detail kullanır. Cok protokollu sistemlerde hata kodu mapping tablosu tutulmalidir; ayni is kurali ihlali her protokolde esdeger kod tasimalidir.

Test stratejisi ve anti-kaliplar

Contract test: her hata senaryosu OpenAPI'de tanimli. Snapshot test JSON govdesini dogrular. Chaos test 503 davranisini olcer. Anti-kaliplar: 200 OK ile { success: false }; stack trace production'da; her endpoint farklı JSON yapisi; anlamsiz generic mesajlar. Hata sozlesmesi API'nin güvenilir yuzudur ve erken tasarım kararlarindan biri olmalidir.

Validation pipeline ve merkezi hata dönüşümü

ASP.NET Core'da istek govdesi once model binding ile deserialize edilir, ardindan DataAnnotations veya FluentValidation çalışır. Validation başarısız oldugunda filter pipeline devreye girer ve Problem Details uretilir. Is kurali ihlalleri domain katmaninda DomainException olarak firlatilir; exception handler bunu uygun type ve status'a map eder. Bu katman ayrimi controller kodunu sade tutar. Her exception tipi icin tek bir mapping noktasi olmalidir; copy-paste handler'lar drift riski tasir.

Bulk işlem API'lerinde kismi başarı mümkün olabilir: 207 Multi-Status veya govdede başarılı/başarısız kayıt listesi. Bu durumda Problem Details tek hata yerine composite yanıt semasi kullanılır. Istemci hangi ogenin başarısız oldugunu ayirt edebilmelidir.

Loglama ve PII maskeleme

Hata loglarinda e-posta, telefon, kredi karti gibi PII maselenmelidir. Problem Details istemciye güvenli mesaj gosterirken log tam baglami (maskelenmis) icerir. Correlation ID istemciden X-Correlation-Id ile alinabilir ve yanita yansitilir. SIEM entegrasyonu icin type alani normalize edilmis event tipi olarak kullanılır.