1 puan yazan GN⁺ 4 시간 전 | 1 yorum | WhatsApp'ta paylaş
  • RFC 10008, istek gövdesindeki sorguyu hedef kaynağın güvenli ve idempotent biçimde işlemesi ve ardından sonucu döndürmesi için HTTP QUERY metodunu tanımlar
  • QUERY, GET'in safe/idempotent niteliği ile POST'un gövde taşıma biçimini birleştirerek uzun URI'ler, URI kodlama maliyeti, loglara sızma ve sorgu kombinasyonu başına kaynaklaştırma yükünü azaltır
  • Sunucu, QUERY isteğini ancak Content-Type ile gövde birbiriyle tutarlıysa işleyebilir; desteklenmeyen türler, gövde uyuşmazlığı ve işlenemeyen sorgular farklı 4xx yanıtlarıyla ayrıştırılabilir
  • Başarılı yanıtta Content-Location sorgu sonucu kaynağını, Location ise aynı sorguyu yeniden çalıştırabilecek bir equivalent resource'u gösterebilir
  • QUERY yanıtları önbelleğe alınabilir, ancak önbellek anahtarının gövde ve metadata'yı da içermesi gerekir; CORS ortamında safelisted method olmadığından preflight gerekir

QUERY'nin çözmeye çalıştığı HTTP sorgu deseni

  • RFC 10008, HTTP QUERY istek metodunu tanımlayan bir Internet Standards Track belgesidir
  • QUERY, hedef kaynağın istek gövdesini işlemesini ve sonucunu yanıt olarak döndürmesini ister
  • POST gibi gövde kullanır, ancak safe ve idempotent olarak tanımlandığı için otomatik yeniden deneme veya yeniden başlatma mümkündür
  • Mevcut GET sorgularında girdiyi URI'ye koymak yaygındır
    • GET /feed?q=foo&limit=10&sort=-published HTTP/1.1
  • Sorgu verisini URI'ye koymak, veri büyüdükçe daha fazla kısıt yaratır
    • Birden fazla bağımsız sistemden geçtiği için gerçek URI boyutu sınırını önceden bilmek zordur
    • HTTP, gönderici ve alıcının en az 8000 octets desteklemesini önerir, ancak yol üzerindeki tüm sistemler için garanti vermez
    • Bazı verileri geçerli bir URI olarak kodlamanın maliyeti yüksektir
    • İstek URI'sinin, istek gövdesine göre loglara düşme veya yer imlerine eklenme olasılığı daha yüksektir
    • Sorgunun doğrudan URI'ye kodlanması, olası her girdi kombinasyonunun ayrı bir kaynak sayılması anlamına gelir

GET ile POST arasındaki anlamı netleştiren bir metot

  • Birçok uygulama, sorguyu GET yerine POST gövdesiyle iletir
    • POST /feed
    • Content-Type: application/x-www-form-urlencoded
    • gövde: q=foo&limit=10&sort=-published
  • Bu yaklaşımın güvenli ve idempotent bir sorgu olup olmadığı, belirli kaynak ve sunucu bilgisi olmadan anlaşılmaz
  • QUERY ise aynı girdiyi istek gövdesiyle gönderirken, metodun kendisini güvenli ve idempotent olarak tanımlar
    • QUERY /feed
    • Content-Type: application/x-www-form-urlencoded
    • gövde: q=foo&limit=10&sort=-published
  • Bu açık anlam sayesinde önbellekleme ve otomatik yeniden deneme gibi HTTP özelliklerini uygulamak kolaylaşır
  • Sunucu, sorgunun kendisine veya belirli bir sorgu sonucuna URI atayarak bunun daha sonra GET isteklerinde kullanılmasını sağlayabilir

QUERY metodunun temel kuralları

  • QUERY, sunucu tarafı bir sorgu başlatmak için kullanılır
  • GET, hedef URI'nin tanımladığı kaynağın temsilini isterken QUERY, hedef kaynağın kapsamı içinde bir sorgu işlemi yürütülmesini ister
  • İstek gövdesi ve medya tipi sorguyu tanımlar; origin server ise işlem kapsamını hedef kaynağa göre belirler
  • Sunucu, Content-Type istek alanı yoksa veya istek gövdesiyle eşleşmiyorsa isteği başarısız saymalıdır
  • Hedef URI'nin query part'ı, diğer tüm HTTP metotlarında olduğu gibi sorgu hedefi kaynağın tanımlanmasına katılır
    • Bu query part'ın sonuca doğrudan etkisi olup olmadığı ve nasıl etki ettiği, kaynağa özgü davranıştır ve bu spesifikasyonun kapsamı dışındadır
  • QUERY, hedef kaynak açısından güvenlidir
    • İstemci, hedef kaynak durumunun değiştirilmesini istemez veya beklemez
    • Sunucunun, ek bilgiye erişmek için HTTP kaynakları oluşturması yasak değildir
  • QUERY idempotenttir; bu nedenle bağlantı hatasından sonra gerekirse yeniden denenebilir veya tekrar gönderilebilir
  • 200 OK yanıtı, sorgunun başarıyla işlendiğini ve sonucun yanıt gövdesine dahil edildiğini gösterir

Medya tipi, uzlaşma ve hata işleme

  • QUERY isteğinin anlamı, istek gövdesi ve medya tipi gibi ilgili metadata'ya göre değişir
  • Gövde ile metadata'sı tutarsız istekler genellikle 4xx Client Error ile reddedilmelidir
  • Hata işleme, isteğin nerede yanlış olduğuna göre değişir
    • Medya tipi bilgisi yoksa istek tanım gereği hatalıdır; bu yüzden 400 gibi bir 4xx durum koduyla başarısız olmalıdır
    • Medya tipi belirtilmiş ama kaynak bunu desteklemiyorsa 415 Unsupported Media Type uygundur
    • Medya tipi ilke olarak bilinse bile hedef kaynağın QUERY anlamı yoksa bu da 415 kapsamına girebilir
    • Medya tipi gerçek istek gövdesiyle uyuşmuyorsa 400 Bad Request döndürülebilir
    • Sunucu, gövdeye bakarak medya tipini tahmin edip eksik ya da yanlış değeri geçersiz kılan bir content sniffing yapamaz
    • Tip ile gövde uyumlu olsa da gerçek sorgu içeriği nedeniyle işlenemiyorsa 422 Unprocessable Content kullanılabilir
    • Sözdizimi olarak geçerli bir SQL sorgusunun var olmayan bir tabloyu hedeflemesi 422 örneğidir
    • İstemcinin Accept ile istediği yanıt medya tipini kaynak desteklemiyorsa 406 Not Acceptable uygundur
  • Accept-Query yanıt alanı, istemciye desteklenen sorgu medya tiplerini bildirebilir

equivalent resource, Content-Location, Location

  • equivalent resource, belirli bir QUERY isteğini ve onun hedefini temsil eden, GET isteklerine yanıt veren kaynaktır
  • equivalent resource hem istek gövdesini hem de metadata'yı dikkate alır
    • Gövdenin medya tipi gibi representation metadata buna dahildir
  • Sunucu equivalent resource için URI atayabilir, ancak bu zorunlu değildir
  • Başarılı yanıt, Content-Location başlığıyla sorgu sonucuna karşılık gelen bir kaynak tanımlayıcısı içerebilir
    • İstemci, belirtilen URI'ye GET göndererek az önce yürütülen sorgu işleminin sonucunu alabilir
    • Bu kaynak geçici olabilir
  • Başarılı yanıt, Location başlığıyla QUERY isteğinin equivalent resource URI'sini içerebilir
    • İstemci, sorgu gövdesini yeniden göndermeden belirtilen URI'ye GET göndererek aynı sorgu işlemini tekrar edebilir
    • Bu URI de geçici olabilir
    • Sonraki istek başarısız olursa istemci, özgün QUERY hedefi ve daha önce gönderdiği gövdeyle yeniden deneyebilir

Yönlendirme ve koşullu istekler

  • Sunucu, QUERY isteğine başka bir URI'ye kullanıcı aracısını yönlendiren dolaylı bir yanıt vermeyi seçebilir
  • 301 Moved Permanently ve 308 Permanent Redirect, hedef kaynağın Location'ın işaret ettiği başka bir URI'ye kalıcı olarak taşındığını gösterir
  • 302 Found ve 307 Temporary Redirect, hedef kaynağın geçici olarak taşındığı anlamına gelir
  • Dört durumda da sunucu, yeni hedef URI'ye benzer bir QUERY isteği gönderilerek özgün isteğin gerçekleştirilebileceğini önerir
  • 301 veya 302 sonrasında POST'u GET'e yönlendiren istisna, QUERY istekleri için geçerli değildir
  • QUERY için 303 See Other, özgün sorgunun Location'ın gösterdiği URI üzerindeki normal bir alma isteğiyle gerçekleştirilebileceğini belirtir
    • HTTP'de bu, yeni hedef URI'ye GET isteği gönderilmesi anlamına gelir
  • Koşullu QUERY'de selected representation, ilgili QUERY isteğinin equivalent resource'una yapılan GET ile aynıdır
  • İstemci, yalnızca koşullu başlıkların belirttiği şartlar sağlandığında sorgu sonucunun yanıt olarak döndürülmesini isteyebilir

Önbellekleme ve Range istekleri

  • QUERY metodunun yanıtları önbelleğe alınabilir ve önbellek daha sonraki QUERY isteklerini karşılamak için kullanılabilir
  • QUERY isteğinin önbellek anahtarı, istek gövdesini ve ilgili metadata'yı içermelidir
  • Önbellek, önbellek anahtarı üretmek için anlamsal olarak önemli olmayan farkları kaldırabilir
    • content encoding'in kaldırılması
    • +json gibi medya subtype suffix'lerinin ifade ettiği biçim geleneğine göre normalizasyon
    • Content-Type'ın ifade ettiği gövde anlamına göre normalizasyon
  • Bu dönüşümler yalnızca önbellek anahtarı üretimi içindir; isteğin kendisini değiştirmez
  • İstemci, no-transform cache directive ile bu dönüşümleri istemediğini belirtebilir, ancak bu directive advisory niteliğindedir
  • QUERY yanıtlarının önbelleğe alınması GET'e göre doğası gereği daha karmaşıktır
    • Önbellek anahtarını belirlemek için istek gövdesinin tamamını okumak gerekir
    • QUERY yanıtı, equivalent resource URI'sini Location ile verirse istemci daha sonra GET'e geçerek işlemi basitleştirebilir
  • QUERY'nin Range Request anlamı GET ile aynıdır
  • Yazım sırasında tanımlı tek range unit olan Byte Range Request, QUERY sonuçları için çok az değer taşır
  • SQL içindeki FETCH FIRST ... ROWS ONLY gibi, sorgu biçiminin kendisinin sonuç sınırlama veya sayfalama sağlaması yaygındır ve bu tür yerleşik özelliklerin kullanılması beklenir

Accept-Query yanıt başlığı

  • Accept-Query yanıt başlığı, kaynağın QUERY metodunu desteklediğini doğrudan bildirir ve kullanılabilecek sorgu biçimi medya tiplerini tanımlar
  • Accept-Query, Structured Fields sözdizimini kullanan bir media range listesidir
  • media range, parametresiz media range değerini taşıyan Token veya String türünde bir List Structured Header Field olarak ifade edilir
  • Medya tipi parametreleri, Structured Field Parameters'a eşlenir
    • String ile Token seçimi anlamsal olarak önemli değildir
    • Alıcı Token'ı String'e dönüştürebilir, ancak alınan türe göre farklı davranmamalıdır
  • Medya tipleri Token'a bire bir eşlenmez; başta rakama izin verilen durumlarda String biçimi kullanılmalıdır
  • Desteklenen wildcard'lar yalnızca */* veya xxxx/* biçimindedir
  • Alan değerinde listelenen tiplerin sırası önemli değildir
  • Accept-Query değeri, aynı path'i paylaşan bir sunucudaki tüm URI'lere uygulanır; query component dikkate alınmaz
  • Aynı kaynak isteği farklı Accept-Query değerleri döndürürse, en son alınan fresh değer kullanılır
  • Örnek şu şekildedir
    • Accept-Query: "application/jsonpath", application/sql;charset="UTF-8"
  • Accept-Query, Accepte benzese de Structured Field olduğu için RFC 9651'in Structured Fields işleme kurallarına uyulmalıdır

Güvenlik değerlendirmeleri ve CORS

  • QUERY, RFC 9110'da tanımlanan tüm HTTP metotlarının genel güvenlik değerlendirmelerini izler
  • QUERY, istek bilgisini URI query component'ine koyma yaklaşımına alternatif olarak kullanılabilir
  • URI'ler, istek gövdelerine göre loglara düşme veya aracı sistemlerce işlenme olasılığı daha yüksek olduğundan, hassas bilgi içeren sorgularda GET yerine QUERY tercih edilmesi için bir gerekçe sunabilir
  • Sunucu, QUERY sonucunu temsil eden geçici kaynaklar oluşturup bunlara URI atadığında, özgün istek gövdesinde loglara yazılmaması gereken hassas bilgiler varsa bu URI'lerde hassas kısımlara yer vermemelidir
  • Önbellek, QUERY gövdesini yanlış normalize ederse veya kaynağın işleme biçiminden önemli ölçüde farklı normalize ederse false positive ile yanlış yanıt döndürebilir
  • CORS uygulayan kullanıcı aracılarının QUERY isteklerinde preflight isteği gerekir
    • QUERY, CORS-safelisted methods kümesinde yer almaz

IANA kaydı ve metot adının seçimi

  • IANA, QUERY metodunu HTTP Method Registry'ye ekler
    • Method Name: QUERY
    • Safe: yes
    • Idempotent: yes
    • Specification: RFC 10008 Section 2
  • IANA, Accept-Query alanını HTTP Field Name Registry'ye ekler
    • Field Name: Accept-Query
    • Status: permanent
    • Structured Type: List
  • HTTP Method Registry'de zaten safe ve idempotent özelliklerine sahip PROPFIND, REPORT, SEARCH bulunuyordu
  • Erken aşamada SEARCH kullanıldı, ancak nihai metot adı QUERY oldu
  • QUERY'nin seçilme nedenleri şunlardır
    • Alternatifler, istek gövdesinde genel medya tipi application/xml kullanıyor ve istek anlamı tamamen gövdeye bağlı oluyordu
    • Alternatiflerin tamamı WebDAV etkinliklerinden türemişti
    • QUERY, URI'nin query component'iyle ilişkisini iyi yakalar

1 yorum

 
GN⁺ 4 시간 전
Hacker News yorumları
  • Güçlü bir motivasyon örneği olsaydı daha ikna edici olurdu, ama GET ile fazla kolay ifade edilebilen bir örnek kullanıldığı için aksine dikkat dağıtıyor
    Büyük JSON filtre yapıları ya da görsel girdisini istek gövdesine koyan bir QUERY hayal etseniz bile, istek gövdesinin önbellek anahtarının bir parçası olması çok tuhaf geliyor. Kullanıcının kontrol ettiği sonsuz önbellek anahtarları ortaya çıkıyor ve yaygın önbellekleme stratejileri pratikte istek gövdesini bit düzeyinde karşılaştırmak veya hash'lemekten ibaret olduğu için kötü niyetli durumlarda önbelleği geçersiz kılmak çok kolaylaşıyor
    Karmaşık filtreleme ya da görsel gibi karmaşık girdiler gerektiren bir hizmet geliştiriyorsanız, önbellekleme muhtemelen HTTP katmanından oldukça uzakta olacaktır. Örneğin join'in tek tek veri sütunları ya da çözümlenmiş görsel girdisinin algısal hash'iyle anahtarlanan embedding'ler gibi, tel üzerindeki tam bit gösteriminden bağımsız olacaktır
    Bunun neden illa genel amaçlı bir şekilde yakalanmak istendiğini anlamıyorum. Bunun yerine POST için "Vary: request-body" gibi yeni bir başlıkla önbellekleme semantiğini ifade etmek çok daha iyi olurdu bence. Tam anlamıyla geriye dönük uyumlu olurdu ve bu davranışın işe yarayabileceği belki %0,1'lik CDN kullanım örnekleri dışında görmezden gelinebilirdi

    • GET'in URI'sindeki sorgu kısmı da pratikte neredeyse sınırsızdır ve kullanıcı kontrolündedir; ayrıca URI'nin parçası olduğu için önbellek anahtarına da girer. Bu yüzden bunun tersinin neden özellikle sorun edildiğini pek anlamıyorum
    • Tarayıcı daha küçük bir önbellek anahtarı istiyorsa gövdenin çarpışmaya dayanıklı hash'ini saklayabilir. Mesela SHA-256 kullanılabilir
      Sorgu parametreleri için de aynen geçerli olmayan bir önbellekleme saldırısı aklıma gelmiyor. Önbelleği taşırmak istiyorsanız benzersiz 30 karakterlik sorgu parametreleri üretmek, 30 MB'lık istek gövdeleri üretmek kadar kolay
    • Tüm kullanım senaryoları açık internet değil ve açık internette yararlı olmaması da standartlaştırılamayacağı anlamına gelmez
      Gerçekte açık internete yönelik sistemler önbellek anahtarı olarak güvenli hash kullanıp bunu her zaman sabit boyutlu yapacaktır. Önbellek anahtarlarında zaten çok uzun olabilen URL'ler ve keyfi başlık değerleri kümeleri de var
    • Görseller de istek gövdesiyle gönderilebilir ama zaten base64 sorgu parametresiyle de yapılabilir. Garip kullanmak isterseniz önerilen her standart kötüye kullanılabilir
      Sorgu parametreli GET de zaten opaktır ve önbelleği geçersiz kılmayı kolaylaştırır
    • Örneğin şu anda üzerinde çalıştığım veritabanı için bir MCP sunucusu yapıyorum. ChatGPT'de commit'ten önce geri alınan bir dry-run POST yapmak istiyorum ama ikisi de sadece tek bir özelliği farklı olan POST isteği olduğundan aracın güvenlik katmanını sık sık tetikliyor. Çeşitli nedenlerle asıl nedeni debug etmek de zor
      Ama QUERY'nin ardından POST kullanmak daha iyi olabilir gibi geliyor. Çünkü bu durumda sadece güvenli bayrağı eklenmiş aynı istek değil, iki farklı istek türü oluyorlar
  • HTML formlarının QUERY desteği ekleyip eklemeyeceğini merak ediyorum
    QUERY idempotent olmak zorunda olduğundan, POST form gönderiminden çıkan sayfayı yenilerken görülen can sıkıcı yeniden gönderim uyarısını önleyebilir

    • HTML formlarında GET/POST dışında daha fazla metod desteği, onlarca yıldır istediğim bir şey. Neyse ki bir WHATWG önerisi var; sesinizi eklemek isterseniz buraya bakın: https://github.com/whatwg/html/pull/11347
    • Formlarla ilgili tuhaf şeylerden biri, form POST'unun sonucunun bir konuma (URL'ye) sahip bir sayfa olması ama o konum üzerinden yüklenememesi. Bildiğim kadarıyla o sayfanın GET değil de POST olduğu bilgisi kullanıcının ya da JS'in görebildiği hiçbir yerde saklanmıyor ve yenileme de garip çalışıyor
      method=QUERY eklenirse bu tuhaflığın bir yeni türü daha olacak
    • Bunu POST-Redirect-GET kalıbı ile çözmek daha iyi
    • Bkz. https://github.com/whatwg/html/issues/12594
    • Başka fiil desteği hiç eklenmedi ama artık yeni bir çağdayız, ne olur bilinmez
  • Hâlâ geçen yüzyıldaymış gibi yapmak isteyenler için: https://www.rfc-editor.org/rfc/rfc10008.txt

    • Böyle uzun ve eksiksiz düz metin belgeleri sanırım sonsuza kadar seveceğim. Çocukken video oyunu FAQ'larına baktığım güzel günleri hatırlatıyor. Pek çok açıdan gerçekten üstün bir bilgi biçimi
    • Biçimlendirme çok güzel. Bunu kurum içi not şablonu olarak kopyalayabilirim. Zamansız
  • “GET isteğine gövde ekleme yaklaşımı IETF çalışma grubunda derinlemesine incelendi, ancak sonunda yeni QUERY metodunu oluşturma yönünde karar verildi. Ayrı bir metod oluşturma kararı, tarihsel birlikte çalışabilirlik sorunları ve HTTP'nin temel mimari tanımına sıkı bağlılık nedeniyle alındı”
    Ama ben birkaç yıldır GET metoduyla istek gövdesi gönderiyorum

    • Bazı load balancer'ların gövdeyi attığı söyleniyor
    • Genel olarak iyi bir fikir değil. Bazı HTTP uygulamalarında bu zaten mümkün değil. Örneğin fetch
      https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/U...
      “GET istekleri gövde içeremez”
      Şeffaf önbellekleme yüzünden tuhaf sorunlar da çıkabilir
  • Artık 5 haneli RFC numaralarına gelmiş olmamız şaşırtıcı

  • Biri RFC 10000'in ne zaman yayımlanacağı üzerine belirsiz bir bahis açmıştı ama numaralar 9998'den doğrudan 10008'e atladı. Kimse kazanamadı
    https://manifold.markets/CollectedOverSpread/when-will-rfc-1...

  • HTTP sorgusunda arama sonuçlarını sorgulamak için QUERY metodu kullanılacak ve sorgu parametreleri eklenmeyecek gibi bir durum oluyor
    İsim kafa karıştırıcı. Çünkü query terimi zaten genel olarak HTTP isteklerini ifade etmek için kullanılıyor
    Sadece RFC başlığını görünce bile kafam karıştı

    • query terimi HTTP isteklerini genel olarak hangi alanda ifade ediyor? Günlük dilde GET isteğine sorgu dendiği olur ama POST, PUT, DELETE için asla denmez
    • Evet. Üstelik bunun illa sorgu olması da gerekmiyor; idempotent etki de olabilir. Belki IPOST, yani idempotent POST demek daha iyi olurdu
      Düzenleme: Aa, önbelleklenebilirlik için QUERY'yi yan etkisiz, yani “güvenli” bir metod olarak tanımlamışlar. Ben karıştırmışım
  • Bu gerçekten sorgu dizgili GET isteklerinin yerini sahada almaya başlarsa, tarayıcı yer imlerinin istek parametrelerini korumayı desteklemesini gerçekten isterim

    • Muhtemelen öyle olmaz. Daha çok bugün sorgu amaçlı POST kullanılan yerlerin yerini alır gibi duruyor
  • Bunun RFC kapsamı dışında olduğunu biliyorum ama bunun kolay bir uzantısı sayesinde JS EventSource'un akışlı yapay zeka sorgularında da çalışabilecek olması güzel
    İstekte gövde gerektiği için herkes POST kullanıyor ve akışlı sonuçlar için yanıtta sıkça text/event-stream protokolü kullanılıyor. Ama gerçekte durum değişmiyor, yani teknik olarak tam oturmuyor ve EventSource da inatla yalnızca GET kullanabiliyor. Bu yüzden birçok API aynı işlevi kendi ayrıştırıcısıyla baştan uyguluyor

  • GET: Content (body) "no defined semantics" ifadesini görünce GET metodunda gövdeye izin vermenin sorun olmayabileceğini düşünmüştüm ama özgün spesifikasyonda GET gövdesi tamamen yok sayılmalı
    Ayrıca isteğin önemli bir kısmı atılabilir bir gövdedeyse önbellekleme de bozulabilir

    • Yalnızca URI içeren GET, kaynağın mevcut temsilini getirme semantiğine sahiptir. Bu, hiperbağın en temel biçimidir ve web'in çalışma biçimi açısından oldukça önemlidir
      GET'e gövde parametreleri eklerseniz aynı URI'yi kullanan iki isteği artık aynı şeyi işaret ediyor sayamazsınız; bu da metodun kısıtını bozar