Temiz Bir RESTful API Tasarımı için 10 Best-Practice

Doğru bir API tasarımı, kullanım kolaylığı, çabuk anlaşılabilirlik, hata tamirinde hız ve kararlılığa katkı sağlar. Ayrıca API arkasındaki aplikasyonun doğru bir yapıyla inşa edilmesinde ve geliştirilmesinde geliştiriciyi olumlu yönlendirir.

Bu maddelerin önem sırasına göre dizilmediğini bildirmeliyim. Bence hepsi birbirini tamamlayıcı pratikler.

  1. İsim kullan, fiil kullanma
    Resource: /cars
    Method: GET
    İş: Araba listesi döndürür
    
    Resource: /cars
    Method: POST
    İş: Araba oluşturur
    
    Resource: /cars
    Method: PUT
    İş: Arabaları topluca replace eder
    
    Resource: /cars
    Method: PATCH
    İş: Arabaları topluca kısmi günceller
    
    Resource: /cars
    Method: DELETE
    İş: Arabaların hepsini siler
    
    Resource: /cars/123
    Method: GET
    İş: ID'si 123 olan arabayı döndürür
    
    Resource: /cars/123
    Method: POST
    İş: Method Not Allowed 405 hatası döndürür
    
    Resource: /cars/123
    Method: PUT
    İş: ID'si 123 olan arabayı replace eder
    
    Resource: /cars/123
    Method: PATCH
    İş: ID'si 123 olan arabayı kısmi günceller
    
    Resource: /cars/123
    Method: DELETE
    İş: ID'si 123 olan arabayı siler
    
    Resource yolu olarak fiil kullanmayın. Şunlar gibi:
    /getAllCars
    /createNewCar
    /deleteAllBlackCars
    
  2. GET metodu ve query parametreleri nesne veya nesnelerin state’ini değiştirmemeli
    Nesnelerin state’ini değiştirmek için POST, PUT, PATCH veya DELETE kullanın. Örneğin şunları kullanmayın:
    GET /cars/123?activate
    GET /cars/123/activate
    
  3. Yalnız çoğul isim kullan
    Tüm resource’lar için şunlarda olduğu gibi yalnızca çoğul isim kullanın:
    /cars/123 ( /car/123 değil)
    /users ( /user değil)
    /settings/sending-notification ( /setting/sending-notification değil)
    
  4. Bir resource eğer başka bir resource ile ilişkili ise sub-resource düzenini kullan
    Resource: /cars/123/drivers
    Method: GET
    İş: ID'si 123 olan arabanın sürücü listesini döndürür
    
    Resource: /cars/123/drivers/456
    Method: GET
    İş: ID'si 123 olan arabanın sürücülerinden ID'si 456 olanı döndürür
    
  5. Serializasyon formatı için HTTP header’larını kullan

    İstemci de sunucu da hangi format’ta iletişim kurması gerektiğini bilmelidir. Bu bilgi HTTP header’ları ile aktarılmalıdır. Content-Type header’ı request format’ını tanımlamak için; Accept header’ı response format’ını veya format listesini bildirmek için kullanılmalıdır.

    Ayrıca serialize çıktı yapısı bir ya da birden fazla parametreye bağlı olacaksa bu da bir header parametresi olarak bildirilmelidir. Örneğin:

    X-Serialization-Groups: Details,DriverDetails
    
  6. HATEOAS kullan

    Hypermedia as the Engine of Application State, daha iyi API navigasyonu sağlayacak olan bir hypertext link kullanımı prensibidir. Örneğin:

    {
      "id": 123,
      "manufacturer": "BMC",
      "drivers": [
        {
          "id": 456,
          "name": "Abdullah Pazarbasi",
          "links": [
            {
              "rel": "self",
              "href": "/api/v2/cars/123/drivers/456"
            }
          ]
        }
      ]
    }
    
  7. Koleksiyonlar için alan seçimi, filtreleme, sıralama ve sayfalama bilgisi sağla
    Alan Seçimi:

    Bir fields query parametresinin içinde virgülle ayrılmış alan isimlerini göndererek seçilen alanlar haricindekilerin değerlerinin null olarak dönmesini sağlayabilirsiniz. Bazen iletişim yükünü azaltmak için işe yarayabilir. Örneğin:

    GET /cars/123?fields=id,manufacturer,model
    
    Filtreleme:

    Süzme için şu örnekteki gibi parametre gönderebilirsiniz:

    GET /cars?color=black&classification=sport
    
    Sıralama:

    Artan ve azalan sıralama bildirmek için birden fazla alan için bile olsa şunun gibi kullanabilirsiniz:

    GET /cars?sort=-manufacturer,+model
    
    Sayfalama:

    offset ve limit parametreleri ile sayfalama sağlayabilirsiniz. Örneğin:

    GET /cars?offset=0&limit=10
    

    total count’u istemciye bildirmek için X-Total-Count header’ını kullanın.

  8. Versiyonla

    Şunun gibi resource yolu öncesi versiyon bildirin:

    GET /api/v2/cars/123
    

    Dikkat edilmesi gereken şeyler version başına v karakteri koymak ve versiyon numarasında nokta ( . ) kullanmamak.

  9. Hataları, HTTP Status Code’ları ile ele al

    Tüm status code’larını kullanmamıza gerek yok. Şunları kullanın:

    200 - OK : Herşey yolunda
    201 - Created : Yeni bir resource oluşturuldu
    202 - Accepted : Güncelleme kabul edildi
    204 - No Content : Resource listesi boş / Resource silindi
    304 - Not Modified : İstemci önbelleklenen veriyi kullanabilir
    

    4xx hataları error-payload’unda açıklanmalıdır.

    400 - Bad Request : Geçersiz request gövdesi / Eksik parametre / Geçersiz parametre
    401 - Unauthorized : User authentication gerekiyor
    403 - Forbidden : Sunucu talebinizi algıladı ve fakat reddetti / Sunucu talebinizi algıladı ve fakat talebi yapmaya yetkiniz yok
    404 - Not Found : URI ardındaki tekil resource mevcut değil
    405 - Method Not Allowed : Geçerli HTTP metodu söz konusu URI için kullanılamaz
    406 - Not Acceptable : İfade biçimi kabul edilemez durumda
    409 - Conflict : Birbiri içinde çelişki bulunan parametre seti alınmış
    415 - Unsupported Media Type : Desteklenmeyen içerik tipi / Desteklenmeyen request/response gövde notasyonu (json, xml vb.)
    422 - Unprocessable Entity : Ön koşulları gerçekleşmemiş olduğu için hedeflenen state değişimi gerçekleştirilemedi
    

    5xx hatalarının detayları production ortamında istemiciye ulaştırılmamalı ve fakat log’lanmalıdır.

    Peki error-payload ne sunmalı? Şu şekilde düzenlenebilir:

    {
      "errors": [
        {
          "userMessage": "Foo",
          "internalMessage": "Bar",
          "code": "E123",
          "moreInfo": "https://services.example.com/api/v2/errors/e123"
        }
      ]
    }
    
  10. HTTP Metodu Override’ına izin ver

    Bazı proxy’ler yalnız GET ve POST metodlarını destekler. Aktüel metod GET ya da POST olsa da X-HTTP-Method-Override header’ının değeri kastedilen metod olarak verilip engel kaldırılabilir.