HATEOAS ve Hypermedia Kontrolleri ile REST Olgunluk Seviyeleri
Bir API'ye "RESTful" demek, onun gerçekten REST prensiplerine uyduğu anlamına gelmez. Richardson Olgunluk Modeli (RMM), bir API'nin REST'e ne kadar yaklaştığını dört seviyede değerlendiren bir çerçeve sunar. Bu modelin zirvesi olan Seviye 3, HATEOAS (Hypermedia as the Engine of Application State) ile tanımlanır. Bu yazıda, modelin dört seviyesini, HATEOAS'ın ne olduğunu ve neden çoğu API'nin Seviye 2'de kaldığını ele alacağız.
1. Richardson Olgunluk Modeli: Dört Seviye
Leonard Richardson tarafından önerilen ve Martin Fowler tarafından popülerleştirilen model, üç temel unsura dayanır: URI tasarımı, HTTP metotlarının kullanımı ve hipermedya bağlantıları.
Seviye 0: The Swamp of POX (Tek Endpoint)
Tüm işlemler tek bir URI üzerinden, genellikle yalnızca POST metoduyla yapılır. HTTP, sadece bir taşıma protokolü olarak görülür. SOAP ve XML-RPC bu seviyenin tipik örnekleridir.
text
POST /api/service
{ "action": "getUser", "userId": 123 }
Seviye 1: Resources (Kaynaklar)
Birden fazla URI kullanılmaya başlanır; her kaynak kendi adresine sahiptir. Ancak hâlâ tek bir HTTP metodu (genellikle POST) kullanılır.
text
POST /api/users/123 POST /api/orders/456
Seviye 2: HTTP Verbs (HTTP Fiilleri)
HTTP metotları (GET, POST, PUT, DELETE) doğru anlamlarıyla kullanılır; durum kodları (200, 404, 500) doğru şekilde döndürülür. Günümüzdeki çoğu REST API bu seviyededir.
text
GET /api/users/123 POST /api/users PUT /api/users/123 DELETE /api/users/123
Seviye 3: Hypermedia Controls (HATEOAS)
Yanıtlara, istemcinin bir sonraki adımda ne yapabileceğini gösteren hipermedya bağlantıları eklenir. API, kendi kendini keşfedilebilir hale gelir.
json
{
"id": 123,
"name": "Ahmet",
"links": [
{ "rel": "self", "href": "/api/users/123", "method": "GET" },
{ "rel": "update", "href": "/api/users/123", "method": "PUT" },
{ "rel": "delete", "href": "/api/users/123", "method": "DELETE" },
{ "rel": "orders", "href": "/api/users/123/orders", "method": "GET" }
]
}
2. HATEOAS Nedir ve Neden Önemlidir?
HATEOAS, "Uygulama Durumunun Motoru Olarak Hipermedya" anlamına gelir. Temel fikir şudur: Bir web sayfasında gezinirken bağlantılara tıklarsınız; API'de de istemci, sunucunun döndürdüğü bağlantıları takip ederek ilerlemelidir.
Sağladığı Avantajlar:
-
Keşfedilebilirlik: İstemci, API'nin yeteneklerini çalışma zamanında keşfeder; tüm URI'leri önceden bilmesi gerekmez.
-
Gevşek Bağlılık: Sunucu, URI şemasını değiştirdiğinde, istemci bağlantıları dinamik takip ettiği için etkilenmez.
-
Kendi Kendini Belgeleme: Yanıtlar, mevcut kaynağı ve olası eylemleri açıklar.
Neden Çoğu API Seviye 3'e Ulaşmaz?
-
Karmaşıklık: HATEOAS, API tasarımına ve geliştirmeye önemli bir karmaşıklık ekler.
-
İstemci Beklentileri: Çoğu istemci geliştiricisi, API'yi dokümantasyon (OpenAPI) okuyarak veya SDK kullanarak tüketmeyi tercih eder; dinamik bağlantı takibi yaygın değildir.
-
Pratik Fayda: Çoğu senaryoda Seviye 2 zaten yeterlidir; HATEOAS'ın getirdiği esneklik, ek maliyete değmeyebilir.
-
Hipermedya Formatları: JSON doğal bir hipermedya formatı değildir; HAL, JSON:API, Siren gibi özel formatlar gerekir.
3. .NET'te HATEOAS Uygulaması
.NET'te HATEOAS uygulamak için birkaç yaklaşım vardır:
A. Manuel Link Ekleme
En temel yöntem, DTO'lara manuel olarak link listesi eklemektir. Bu, tam kontrol sağlar ancak kod tekrarına yol açar.
B. AspNetCore.Hateoas Kütüphanesi
Filippo De Santis tarafından geliştirilen bu kütüphane, [Route] attribute'lerini kullanarak link'leri otomatik oluşturur. AddHateoas() ve LinkGenerator üzerinden çalışır.
C. RestWithASPNET.HATEOAS
ISupportsHyperMedia arayüzü ve HyperMediaFilter ile attribute tabanlı bir yaklaşım sunar.
D. MVC.Hateoas (NuGet)
En yaygın kullanılan paketlerden biridir. [Route] attribute'lerinden link üretir; ASP.NET Core MVC ile uyumludur .
Örnek (Manuel Yaklaşım):
csharp
public class UserDto
{
public int Id { get; set; }
public string Name { get; set; }
public List<LinkDto> Links { get; set; } = new();
}
public class LinkDto
{
public string Rel { get; set; }
public string Href { get; set; }
public string Method { get; set; }
}
// Controller'da
var dto = new UserDto { Id = user.Id, Name = user.Name };
dto.Links.Add(new LinkDto { Rel = "self", Href = Url.Action(nameof(GetUser), new { id = user.Id }), Method = "GET" });
dto.Links.Add(new LinkDto { Rel = "update", Href = Url.Action(nameof(UpdateUser), new { id = user.Id }), Method = "PUT" });
4. Ne Zaman HATEOAS Kullanmalı?
| Senaryo | Öneri |
|---|---|
| Büyük, karmaşık, uzun ömürlü API | HATEOAS değerlendirilebilir |
| Farklı istemciler (web, mobil, 3. parti) | HATEOAS, istemcilerin bağımsız evrilmesini kolaylaştırır |
| Basit CRUD API'leri | Seviye 2 yeterli |
| Dahili mikroservis iletişimi | Seviye 2; HATEOAS gereksiz karmaşıklık |
| Public API (Stripe, GitHub gibi) | Çoğu, dokümantasyon + Seviye 2 tercih eder |
5. En İyi Pratikler
| Pratik | Açıklama |
|---|---|
| Tutarlı link yapısı kullanın | rel, href, method alanlarını standartlaştırın. |
| Hipermedya formatı seçin | HAL veya JSON:API gibi standart formatlar, istemci uyumluluğunu artırır. |
| Tüm eylemleri değil, mevcut duruma uygun olanları listeleyin | Kullanıcı yetkisi yoksa "delete" link'i göndermeyin. |
| Dokümantasyonu ihmal etmeyin | HATEOAS, OpenAPI dokümantasyonunun yerini almaz; tamamlar. |
Sonuç
Richardson Olgunluk Modeli, bir API'nin REST'e ne kadar uyduğunu anlamak için değerli bir çerçevedir. Seviye 2, günümüzde çoğu API için yeterli ve pratiktir. Seviye 3 (HATEOAS) ise teorik olarak en "RESTful" yaklaşımdır; ancak getirdiği karmaşıklık ve istemci ekosisteminin dokümantasyon odaklı alışkanlıkları nedeniyle nadiren tam olarak uygulanır. Yine de sayfalama, karmaşık iş akışları ve çoklu istemci senaryolarında HATEOAS'ın seçici kullanımı, API'nize değer katabilir. Unutmayın: En yüksek olgunluk seviyesi, her zaman en iyi seçenek değildir; doğru seviye, ihtiyacınıza ve ekibinizin kapasitesine göre belirlenir.