← Radar

Konu: Altyapı2 dk okuma

HTTP'ye yeni metot: QUERY, gövdesi olan bir GET

Bu neden önemli?

Arama ve filtreleme yapan neredeyse her API, GET ile POST arasında sıkışıp kalıyordu. QUERY bu boşluğu dolduruyor. Desteği yeni olsa da, API tasarlıyorsan ne olduğunu bilmeye değer.

Önce iki kavram: Güvenli ve tekrarlanabilir

HTTP’de her metodun bir anlamı var. Bu anlam, araya giren her sistemin (tarayıcı, proxy, önbellek, CDN) isteği nasıl ele alacağını belirliyor.

  • Güvenli (safe): İstek sunucuda bir şey değiştirmiyor, sadece okuyor. GET böyle.
  • Tekrarlanabilir (idempotent): Aynı isteği iki kez göndermek, bir kez göndermekle aynı sonucu veriyor. Bağlantı koptuğunda istek gönül rahatlığıyla yeniden denenebiliyor.

GET ikisini de sağlıyor, bu yüzden önbelleğe alınabiliyor ve otomatik tekrar denenebiliyor. POST ise ikisini de sağlamıyor. POST’u tekrar göndermek, örneğin iki kez sipariş vermek anlamına gelebilir.

Sorun: Arama nereye sığacak?

Basit bir arama URL’ye sığar: /urunler?renk=mavi&sirala=fiyat. Ama filtre büyüdükçe işler bozuluyor:

  • URL’lerin bir uzunluk sınırı var ve bu sınır yol üzerindeki her sistemde farklı olabiliyor.
  • İç içe yapıları ve listeleri URL’de yazmanın tek bir standart yolu yok.
  • URL’ler kayıtlara (log) ve yer imlerine düşüyor. Hassas bir arama terimi de onlarla birlikte gidiyor.

“GET isteğine gövde ekleyelim” fikri pratikte işe yaramıyor. Standart bunu yasaklamıyor ama anlam da vermiyor. Bazı sunucular ve proxy’ler gövdeyi siliyor, bazıları isteği reddediyor.

Bu yüzden çoğu API, aramaları POST ile yapıyor. Sorguların çoğunu POST ile gönderen GraphQL buna iyi bir örnek. Çalışıyor, ama dışarıdan bakan hiçbir sistem bu POST’un sadece okuma yaptığını bilemiyor. Önbellek de devre dışı kalıyor, güvenli tekrar deneme de.

Çözüm: QUERY

QUERY, POST gibi veriyi isteğin gövdesinde taşıyor. Ama GET gibi güvenli ve tekrarlanabilir olduğunu açıkça söylüyor:

QUERY /urunler HTTP/1.1
Content-Type: application/json

{"renk": "mavi", "fiyat": {"max": 500}, "sirala": "fiyat"}

RFC’deki önemli ayrıntılar:

  • Önbellek: Cevaplar önbelleğe alınabiliyor. Ama önbellek, anahtarını oluştururken gövdeyi de hesaba katmak zorunda. Bu GET’e göre daha zor, çünkü önbelleğin önce bütün gövdeyi okuması gerekiyor.
  • Accept-Query: Sunucu bu başlıkla QUERY’de hangi biçimleri kabul ettiğini söyleyebiliyor. Örneğin JSON, form verisi ya da SQL.
  • Sonuca adres vermek: Sunucu, cevapta sorgu ya da sonuç için bir adres döndürebiliyor. İstemci sonraki seferlerde o adrese normal bir GET ile gidebiliyor.
  • CORS: Tarayıcıdan başka bir siteye gönderilen QUERY isteği, önce bir ön kontrol (preflight) isteği gerektiriyor.

Syntax’ın 1020. bölümünde bu, 16 yıl sonra HTTP’ye gelen ilk yeni metot olarak konuşuldu. Bir önceki, 2010’da RFC 5789 ile gelen PATCH’ti.

Hemen kullanmalı mısın?

Acele etme. Kreya’nın yazısında belirtildiği gibi, destek henüz çok sınırlı. Birçok proxy, güvenlik duvarı ve sunucu bilmediği metotları reddediyor. HTML formları da hâlâ sadece GET ve POST gönderebiliyor.

Pratik kurallar:

  • Basit filtreler URL’ye sığıyorsa GET ile devam et. Paylaşılabilir ve yer imine eklenebilir.
  • Büyük ve karmaşık okuma isteklerini bugün POST ile yapıyorsan, QUERY desteğini önce kendi altyapında test et.
  • Kendi önbellek katmanını yazıyorsan, gövdeyi anahtara katmayı unutma.

Düşün

  • Kullandığın API’lerde sadece okuma yaptığı hâlde POST ile çalışan hangi uç noktalar var?
  • Bir arama URL’si kayıtlara düşse, içinde görmek istemeyeceğin bir bilgi olur muydu?
Kaynaklar (4, İngilizce)

Kendi cümlelerimizle yazılmış bir özettir, çeviri değildir. Tüm kaynaklar yukarıda.