2026'da REST: En İyi Uygulama, Sürüm Oluşturma ve Richardson Olgunluk Modeli
Kendilerini "RESTful" olarak adlandıran çoğu API değildir. HTTP gibi kullanıyorlar taşıyın, format olarak JSON'u seçin ve orada durun. Richardson Olgunluk Modeli, 2008 yılında Leonard Richardson tarafından tanıtılan ve Martin Fowler tarafından popüler hale getirilen Genel bir HTTP API'sini (düzey 0) gerçek bir API'den ayıran dört düzeyde ölçeklendirme RESTful (HATEOAS ile seviye 3).
Ancak mimari mükemmeliyetçilik bu kılavuzun amacı değil. Amaç sana öğretmek REST API'leri oluşturmak için doğru, bakımı yapılabilir ve iyi belgelenmiş: Uygun HTTP anlambilimini kullanın, zaman içinde sürdürülebilir sürüm oluşturmayı uygulayın, yönetin ETag ile etkili bir şekilde önbelleğe alın ve sözleşmeyi OpenAPI 3.1 ile belgeleyin. Bunlar Profesyonel bir API ile tüketiciler için sorunlara neden olan bir API arasındaki gerçek farklar.
Ne Öğreneceksiniz
- Somut örneklerle Richardson Olgunluk Modeli'nin 4 seviyesi
- Doğru HTTP semantiği: yöntemler, durum kodları, başlıklar
- Bağımsızlık ve güvenli yöntemler: pratik uygulamalarla teorik temeller
- Sürüm oluşturma stratejileri: URI, başlık ve ek değişiklikler aracılığıyla sürüm oluşturma
- Verimli önbelleğe alma için ETag ve koşullu istekler
- OpenAPI 3.1: belge yapısı ve en iyi uygulamalar
Richardson Olgunluk Modeli: 4 Düzey
Richardson Olgunluk Modeli, bir API'nin "RESTfulness"ını belirli bir ölçekte ölçer 0 ila 3. Bu seviyeleri anlamak mimari boşlukların belirlenmesine yardımcı olur mevcut API'lere ekleyin ve doğru düzeyde yenilerini oluşturun.
Seviye 0: Aktarım Olarak HTTP (Tünel Açma)
// Livello 0: tutto su un unico endpoint, azione nel body
POST /api
Content-Type: application/json
{
"action": "getUser",
"id": 123
}
POST /api
{
"action": "createUser",
"name": "Federico",
"email": "federico@example.com"
}
// HTTP e solo un canale: la semantica e tutta nell'applicazione
// Nessun caching possibile, nessuna semantica uniforme
Seviye 1: Kaynaklar (Anlamlı URI)
// Livello 1: URL per risorse, ma ancora solo POST
POST /users/123 // Non ha senso: POST per leggere?
POST /users/create
POST /users/delete/123
POST /users/get/all
// Migliore, ma i verbi HTTP non sono usati semanticamente
Seviye 2: HTTP Fiilleri (standart seviye)
// Livello 2: URL meaningful + verbi HTTP corretti + status codes
GET /users -> 200 OK con lista
GET /users/123 -> 200 OK con utente, 404 Not Found
POST /users -> 201 Created con Location header
PUT /users/123 -> 200 OK aggiornato, 404 Not Found
PATCH /users/123 -> 200 OK parzialmente aggiornato
DELETE /users/123 -> 204 No Content, 404 Not Found
// Questo e il livello che la maggior parte delle API raggiunge
// ed e generalmente sufficiente per la produzione
Seviye 3: HATEOAS (Uygulama Durumunun Motoru Olarak Hipermedya)
// Livello 3: ogni risposta contiene link alle azioni disponibili
GET /users/123
-> 200 OK
{
"id": 123,
"name": "Federico",
"email": "federico@example.com",
"status": "active",
"_links": {
"self": { "href": "/users/123" },
"orders": { "href": "/users/123/orders" },
"deactivate": { "href": "/users/123/deactivate", "method": "POST" },
"update": { "href": "/users/123", "method": "PUT" }
}
}
// Il client non deve "sapere" a priori gli URL: li scopre dalle risposte
// Permette di cambiare URL senza rompere i client (in teoria)
HATEOAS: Buna değer mi?
HATEOAS teorik olarak zariftir ancak pratikte nadiren uygulanır. Sebepler:
- Yanıt boyutunu önemli ölçüde artırır
- Ancak istemciler genellikle performans için URL'leri "sabit kodlar"
- Bağlantılarda gezinmek için özel araçlar gerektirir
- Çoğu ekip bunun yerine OpenAPI'yi sözleşme olarak kullanıyor
Seviye 2 + OpenAPI 3.1 ve 2026'daki çoğu API için pragmatik mükemmel nokta. HATEOAS esas olarak URL istikrarının uzun vadeli olduğu genel API'lerde anlamlıdır Terim ve eleştiri.
Doğru HTTP semantiği
HTTP fiillerini doğru anlambilimle kullanmak yalnızca estetik bir sorun değildir: etkisi vardır önbelleğe alma, geçicilik ve istemcilerin istekleri güvenli bir şekilde geri çekme yeteneği.
// Proprietà dei metodi HTTP
Metodo | Safe | Idempotente | Body richiesta | Uso corretto
--------|------|-------------|----------------|----------------------------------
GET | SI | SI | No | Lettura, query, ricerca
HEAD | SI | SI | No | Verifica esistenza, metadata
OPTIONS | SI | SI | No | CORS preflight, capabilities
POST | NO | NO | SI | Creazione, azioni non-idempotenti
PUT | NO | SI | SI | Sostituzione completa di risorsa
PATCH | NO | NO* | SI | Modifica parziale
DELETE | NO | SI | Opzionale | Eliminazione
// *PATCH puo essere reso idempotente con patch semantics JSON Patch (RFC 6902)
Güvenli bu, isteğin sunucu tarafında hiçbir yan etkisinin olmadığı anlamına gelir (sunucu durumu değiştirmez). Bir müşteri sonuçsuz bir GET'te "F5'e basabilir".
İdempotent birden fazla özdeş isteğin aynı şeyi ürettiği anlamına gelir tek bir isteğin sonucu. Yeniden denemeler için çok önemlidir: DELETE sırasında ağ çökerse, müşteri birden fazla silme korkusu olmadan tekrar deneyebilir.
Durum Kodları: Doğru Olanları Kullanın
Kötüye kullanımı 200 OK her şey için (gövde hataları dahil) ve anti-kalıplardan biri için
daha yaygın. Doğru kodları kullanmak istemcilerin, proxy'lerin ve izleme araçlarının
Cevapları doğru yorumlayın:
// Status codes piu importanti con esempi di uso corretto
// 2xx: Success
200 OK - GET, PUT, PATCH con risorsa nel body
201 Created - POST che crea una risorsa (+ Location header)
202 Accepted - Operazione asincrona accettata (non ancora completata)
204 No Content - DELETE, PUT/PATCH senza body di risposta
// 3xx: Redirection
301 Moved Permanently - Redirect permanente (aggiornare i bookmark)
302 Found - Redirect temporaneo
304 Not Modified - ETag/If-None-Match: risorsa non cambiata, usa la cache
// 4xx: Client Error (il client ha sbagliato)
400 Bad Request - Input malformato, schema validation fallita
401 Unauthorized - Non autenticato (serve login)
403 Forbidden - Autenticato ma non autorizzato
404 Not Found - Risorsa non trovata
405 Method Not Allowed - Metodo HTTP non supportato su questo endpoint
409 Conflict - Conflitto di stato (es: email gia esistente)
410 Gone - Risorsa eliminata permanentemente (vs 404)
422 Unprocessable Entity - Sintassi ok ma semantica invalida
429 Too Many Requests - Rate limit raggiunto (+ Retry-After header)
// 5xx: Server Error (colpa del server)
500 Internal Server Error - Errore generico non gestito
502 Bad Gateway - Errore dal backend upstream
503 Service Unavailable - Server temporaneamente non disponibile
504 Gateway Timeout - Timeout dal backend upstream
PUT ve PATCH: Önemli Ayrım
PUT ve PATCH arasındaki karışıklık yaygındır ancak somut sonuçları vardır:
// PUT: sostituzione COMPLETA della risorsa (idempotente)
// Se ometti un campo, viene azzerato!
PUT /users/123
{
"name": "Federico Calo",
"email": "federico@example.com"
// Se il campo "phone" non e incluso, viene rimosso!
}
// PATCH: modifica PARZIALE (solo i campi specificati)
PATCH /users/123
{
"name": "Federico Calo"
// Solo name viene aggiornato, email e phone rimangono invariati
}
// PATCH con JSON Patch (RFC 6902): piu preciso e idempotente
PATCH /users/123
Content-Type: application/json-patch+json
[
{ "op": "replace", "path": "/name", "value": "Federico Calo" },
{ "op": "add", "path": "/phone", "value": "+39 333 1234567" },
{ "op": "remove", "path": "/tempNote" }
]
Sürüm oluşturma stratejileri
Sürüm oluşturma, genel bir API tasarlarken en önemli kararlardan biridir. Bir kez Müşterilerin bir API'ye bağımlı olması, sözleşmenin değiştirilmesi uygulamalarının bozulmasına neden olur. Le Ana stratejilerin farklı değiş-tokuşları vardır:
1. URI Sürümü Oluşturma (en yaygın)
GET /api/v1/users // Versione 1
GET /api/v2/users // Versione 2 con campi aggiuntivi
// Vantaggi:
// - Visibile e ovvio
// - Cacheable a livello HTTP (l'URL e diverso)
// - Facile da esplorare con il browser
// - Semplice da loggare e monitorare
// Svantaggi:
// - "Sporco" semanticamente (la versione non e parte della risorsa)
// - Proliferazione di URL nel tempo
2. Başlık Sürümü Oluşturma
GET /api/users
Accept: application/vnd.myapi.v2+json
// oppure
API-Version: 2
// Vantaggi:
// - URL "puliti"
// - Piu vicino alla semantica HTTP originale
// Svantaggi:
// - Non cacheable con HTTP standard (Cache-Vary header necessario)
// - Invisibile dalla URL (difficile da debuggare)
// - Meno intuitivo per i nuovi consumatori dell'API
3. Eklemeli Değişiklikler Yoluyla Sürüm Oluşturma (en iyisi)
// Strategia: non cambiare mai, solo aggiungere (non rompere mai i client)
// V1 risposta:
GET /api/users/123
{
"id": 123,
"name": "Federico",
"email": "federico@example.com"
}
// Aggiungi campi senza versione (i client vecchi ignorano i nuovi campi):
GET /api/users/123
{
"id": 123,
"name": "Federico",
"email": "federico@example.com",
"createdAt": "2025-01-15T10:30:00Z", // AGGIUNTO: non rompe i client vecchi
"avatarUrl": null // AGGIUNTO: nullable per retrocompat
}
// Quando DEVI rompere (rare):
// - Rimuovere un campo -> versione nuova
// - Cambiare tipo di un campo -> versione nuova
// - Cambiare semantica di un campo -> versione nuova
ETag ve Koşullu İstekler
L'ETag (Varlık Etiketi) ve önbelleği yönetmek için bir HTTP mekanizması ve iyimser rekabet. Her kaynağın kendi sürümünü tanımlayan bir karma değeri veya zaman damgası vardır akım:
// Server: risposta con ETag
GET /users/123
->
200 OK
ETag: "abc123def456"
Cache-Control: max-age=300
{
"id": 123,
"name": "Federico",
"version": 3
}
// Client: richiesta condizionale con If-None-Match
GET /users/123
If-None-Match: "abc123def456"
->
304 Not Modified // Risorsa non cambiata, usa la cache!
// Nessun body = traffico ridotto
// Se la risorsa e cambiata:
GET /users/123
If-None-Match: "abc123def456"
->
200 OK
ETag: "xyz789new123" // Nuovo ETag
{ /* dati aggiornati */ }
// ETag per concorrenza ottimistica (prevenire aggiornamenti in conflitto):
PUT /users/123
If-Match: "abc123def456" // "Aggiorna SOLO se la versione e ancora questa"
{...}
->
200 OK // Aggiornamento riuscito, nessun conflitto
// oppure
412 Precondition Failed // Qualcun altro ha modificato la risorsa!
// Il client deve rileggere prima di riaggiornare
OpenAPI 3.1 ile belgeleme
OpenAPI 3.1, REST API'lerini belgelemeye yönelik endüstri standardıdır. Güzel bir OpenAPI belgesi yazılı resmi bir sözleşme görevi görür, istemci SDK'sının oluşturulmasına olanak tanır ve yetkiler sağlar Swagger UI veya Redoc ile etkileşimli belgeler:
// openapi.yaml - Struttura base di un documento OpenAPI 3.1
openapi: 3.1.0
info:
title: User Management API
version: 1.2.0
description: |
API per la gestione degli utenti dell'applicazione.
## Autenticazione
Usa Bearer token JWT nell'header Authorization.
contact:
name: API Support
email: api@example.com
license:
name: MIT
servers:
- url: https://api.example.com/v1
description: Production
- url: https://staging-api.example.com/v1
description: Staging
paths:
/users:
get:
operationId: listUsers
summary: Lista utenti
tags: [Users]
parameters:
- name: page
in: query
schema: { type: integer, minimum: 1, default: 1 }
- name: limit
in: query
schema: { type: integer, minimum: 1, maximum: 100, default: 20 }
- name: search
in: query
schema: { type: string }
responses:
'200':
description: Lista utenti paginata
content:
application/json:
schema:
$ref: '#/components/schemas/UserListResponse'
'401':
$ref: '#/components/responses/Unauthorized'
post:
operationId: createUser
summary: Crea utente
tags: [Users]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUserRequest'
responses:
'201':
description: Utente creato
headers:
Location:
schema: { type: string }
description: URL del nuovo utente
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'400':
$ref: '#/components/responses/BadRequest'
'409':
description: Email gia esistente
components:
schemas:
User:
type: object
required: [id, name, email, createdAt]
properties:
id: { type: integer, format: int64, readOnly: true }
name: { type: string, minLength: 1, maxLength: 100 }
email: { type: string, format: email }
createdAt: { type: string, format: date-time, readOnly: true }
CreateUserRequest:
type: object
required: [name, email, password]
properties:
name: { type: string, minLength: 1, maxLength: 100 }
email: { type: string, format: email }
password: { type: string, minLength: 8, writeOnly: true }
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
security:
- bearerAuth: []
Hata Yanıtları için Desen
Hata yanıtlarına yönelik tutarlı bir yapı, geliştiriciyi önemli ölçüde iyileştirir API tüketici deneyimi. Standart RFC 9457 (Sorun Ayrıntıları) 2026 yılında da tercih edilen seçenek haline geldi:
// RFC 9457 Problem Details for HTTP APIs
// Content-Type: application/problem+json
// 400 Bad Request
{
"type": "https://example.com/errors/validation-error",
"title": "Validation Error",
"status": 400,
"detail": "The request body contains invalid data",
"instance": "/api/users",
"errors": [
{
"field": "email",
"message": "Invalid email format",
"value": "not-an-email"
},
{
"field": "password",
"message": "Password must be at least 8 characters",
"value": null
}
]
}
// 409 Conflict
{
"type": "https://example.com/errors/duplicate-email",
"title": "Duplicate Email",
"status": 409,
"detail": "An account with this email already exists",
"instance": "/api/users",
"email": "federico@example.com"
}
// 429 Too Many Requests
{
"type": "https://example.com/errors/rate-limited",
"title": "Rate Limit Exceeded",
"status": 429,
"detail": "Too many requests. Retry after 60 seconds.",
"retryAfter": 60
}
Sonuçlar ve Sonraki Adımlar
2026'da profesyonel bir REST API, Richardson Olgunluk Modeli'nin 2. düzeyinde çalışır (kaynaklar + doğru HTTP fiilleri + uygun durum kodları), önbelleğe alma ve iyimser eşzamanlılık için ETag'i kullanın, ek değişikliklere dayalı sürdürülebilir versiyonlamayı benimser ve resmi sözleşmeyi belgelendirir OpenAPI 3.1. Çoğu durumda HATEOAS seviye 3'e ulaşmak gerekli değildir.
Bir sonraki makale inceliyor GraphQL derinlemesine: sistem nasıl çalışıyor çözümleyicilerin sayısı, çünkü N+1 sorunu en yaygın mimari risktir ve DataLoader olarak Veritabanı sorgularının toplu olarak işlenmesini çözer.
Seri: API Tasarımı — REST, GraphQL, gRPC ve tRPC Karşılaştırması
- Madde 1: 2026'da API Ortamı - Karar Matrisi
- Madde 2 (bu): 2026'da REST — En İyi Uygulama, Sürüm Oluşturma ve Richardson Olgunluk Modeli
- Makale 3: GraphQL — Sorgu Dili, Çözümleyici ve N+1 Sorunu
- Madde 4: GraphQL Federasyonu - Üst Grafik, Alt Grafik ve Apollo Yönlendirici
- Madde 5: gRPC — Protobuf, Performans ve Hizmetten Hizmete İletişim
- Madde 6: tRPC — Kod Oluşturmadan Uçtan Uca Güvenlik Türü
- Madde 7: Web Kancaları — Kalıplar, Güvenlik ve Yeniden Deneme Mantığı
- Madde 8: API Sürümü Oluşturma - URI, Başlık ve Kullanımdan Kaldırma Politikası
- Madde 9: Hız Sınırlama ve Azaltma - Algoritmalar ve Uygulamalar
- Makale 10: Hibrit API Mimarisi — 2026'da REST + tRPC + gRPC







