RFC 10008: Metode HTTP QUERY baru
(rfc-editor.org)- RFC 10008 mendefinisikan metode HTTP QUERY yang mengembalikan hasil setelah resource target memproses kueri secara aman dan idempoten yang dikirim dalam body permintaan
- QUERY menggabungkan sifat safe/idempotent milik GET dengan cara pengiriman body milik POST, sehingga mengurangi URI yang panjang, biaya encoding URI, paparan di log, dan beban menjadikan setiap kombinasi kueri sebagai resource terpisah
- Server hanya dapat memproses permintaan QUERY jika Content-Type dan body permintaannya konsisten; tipe yang tidak didukung, ketidaksesuaian body, dan kueri yang tidak dapat diproses dapat dibedakan dengan respons 4xx yang berbeda
- Respons yang berhasil dapat memberi tahu resource hasil kueri lewat Content-Location, dan equivalent resource untuk menjalankan ulang kueri yang sama lewat Location
- Respons QUERY dapat di-cache, tetapi cache key harus mencakup body dan metadata; di lingkungan CORS, metode ini bukan safelisted method sehingga memerlukan preflight
Pola kueri HTTP yang ingin diselesaikan oleh QUERY
- RFC 10008 adalah dokumen Internet Standards Track yang mendefinisikan metode permintaan QUERY di HTTP
- QUERY meminta resource target memproses body permintaan dan mengembalikan hasilnya dalam respons
- Seperti POST, metode ini menggunakan body, tetapi didefinisikan sebagai safe dan idempotent sehingga dapat di-retry atau dijalankan ulang secara otomatis
- Kueri GET yang ada biasanya menaruh input di URI
GET /feed?q=foo&limit=10&sort=-published HTTP/1.1
- Menaruh data kueri di URI membuat batasan makin besar saat data membesar
- Karena melewati banyak sistem independen, sulit mengetahui batas ukuran URI yang nyata sebelumnya
- HTTP merekomendasikan pengirim dan penerima mendukung setidaknya 8000 octets, tetapi itu tidak menjamin semua sistem di sepanjang jalur
- Beberapa data mahal untuk di-encode menjadi URI yang valid
- URI permintaan lebih mungkin tercatat di log atau masuk ke bookmark dibanding body permintaan
- Jika kueri di-encode langsung ke URI, setiap kombinasi input yang mungkin diperlakukan sebagai resource terpisah
Metode yang memperjelas makna di antara GET dan POST
- Banyak implementasi mengirim kueri lewat body POST alih-alih GET
POST /feedContent-Type: application/x-www-form-urlencoded- Body:
q=foo&limit=10&sort=-published
- Dengan cara ini, tanpa pengetahuan tentang resource dan server tertentu, tidak terlihat apakah kuerinya aman dan idempoten
- QUERY mengirim input yang sama di body permintaan, tetapi metodenya sendiri bersifat aman dan idempoten
QUERY /feedContent-Type: application/x-www-form-urlencoded- Body:
q=foo&limit=10&sort=-published
- Makna eksplisit ini memudahkan penerapan fitur HTTP seperti caching dan retry otomatis
- Server dapat memberi URI pada kueri itu sendiri atau pada hasil kueri tertentu untuk dipakai dalam permintaan GET berikutnya
Aturan inti metode QUERY
- QUERY digunakan untuk memulai kueri di sisi server
- GET meminta representasi dari resource yang diidentifikasi oleh URI target, sedangkan QUERY meminta dilakukannya operasi kueri dalam cakupan resource target
- Body permintaan dan media type mendefinisikan kueri, dan origin server menentukan cakupan operasi berdasarkan resource target
- Server harus menggagalkan permintaan jika field permintaan Content-Type tidak ada atau tidak cocok dengan body permintaan
- Query part dari URI target ikut serta dalam identifikasi resource target, sama seperti pada semua metode HTTP
- Apakah query part itu langsung memengaruhi hasil dan bagaimana caranya adalah perilaku khusus resource dan di luar cakupan spesifikasi ini
- QUERY aman dari sudut pandang resource target
- Klien tidak meminta atau mengharapkan perubahan status resource target
- Server tetap tidak dilarang membuat resource HTTP yang dapat diakses untuk mengambil informasi tambahan
- QUERY bersifat idempoten, sehingga dapat di-retry atau diulang bila perlu setelah kegagalan koneksi
- Respons
200 OKmenunjukkan kueri berhasil diproses dan hasilnya disertakan dalam body respons
Media type, negosiasi, dan penanganan kesalahan
- Makna permintaan QUERY bergantung pada body permintaan dan metadata terkait seperti media type
- Permintaan yang body dan metadatanya tidak konsisten umumnya harus ditolak dengan 4xx Client Error
- Penanganan kesalahan berbeda tergantung di mana letak kesalahannya
- Jika tidak ada informasi media type, permintaan salah secara definisi sehingga harus gagal dengan status 4xx seperti
400 - Jika media type ditentukan tetapi tidak didukung resource, maka
415 Unsupported Media Typesesuai - Meski media type itu dikenal secara umum, jika tidak ada makna QUERY untuk resource target, itu juga termasuk kasus
415 - Jika media type tidak cocok dengan body permintaan yang sebenarnya, server dapat mengembalikan
400 Bad Request - Server tidak boleh melakukan content sniffing dengan melihat body untuk menebak media type lalu menimpa nilai yang hilang atau salah
- Jika tipe dan body cocok tetapi isi kueri itu sendiri tidak dapat diproses, dapat digunakan
422 Unprocessable Content - Contoh
422adalah kueri SQL yang sintaksnya benar tetapi menunjuk ke tabel yang tidak ada - Jika resource tidak mendukung media type respons yang diminta klien lewat
Accept, maka406 Not Acceptablesesuai
- Jika tidak ada informasi media type, permintaan salah secara definisi sehingga harus gagal dengan status 4xx seperti
- Field respons
Accept-Querydapat memberi tahu klien media type kueri yang didukung
equivalent resource, Content-Location, Location
- equivalent resource adalah resource yang merepresentasikan permintaan QUERY tertentu beserta targetnya, dan merespons permintaan GET
- Equivalent resource mempertimbangkan body permintaan dan metadata sekaligus
- Termasuk representation metadata seperti media type dari body
- Server dapat memberikan URI pada equivalent resource, tetapi tidak wajib
- Respons yang berhasil dapat menyertakan identifier resource yang sesuai dengan hasil kueri lewat header Content-Location
- Klien dapat mengirim GET ke URI yang ditunjukkan untuk mengambil hasil dari operasi kueri yang baru saja dilakukan
- Resource itu dapat bersifat sementara
- Respons yang berhasil dapat menyertakan URI equivalent resource dari permintaan QUERY lewat header Location
- Klien dapat mengirim GET ke URI yang ditunjukkan untuk mengulangi operasi kueri yang sama tanpa mengirim ulang body kueri
- URI ini juga dapat bersifat sementara
- Jika permintaan berikutnya gagal, klien dapat mencoba lagi dengan target QUERY asli dan body yang sebelumnya dikirim
Pengalihan dan permintaan bersyarat
- Untuk permintaan QUERY, server dapat memilih respons tidak langsung yang mengalihkan user agent ke URI lain
301 Moved Permanentlydan308 Permanent Redirectmenunjukkan resource target telah dipindahkan secara permanen ke URI lain yang ditunjuk Location302 Founddan307 Temporary Redirectberarti perpindahan sementara dari resource target- Dalam keempat kasus itu, server menyarankan bahwa permintaan asli dapat dijalankan dengan mengirim permintaan QUERY serupa ke URI target yang baru
- Pengecualian yang mengalihkan POST menjadi GET setelah
301atau302tidak berlaku untuk permintaan QUERY 303 See Otheruntuk QUERY menunjukkan bahwa kueri asli dapat dijalankan sebagai permintaan pengambilan biasa terhadap URI yang ditunjuk Location- Dalam HTTP, ini berarti mengirim permintaan GET ke URI target yang baru
- Dalam QUERY bersyarat, selected representation sama dengan GET terhadap equivalent resource dari permintaan QUERY tersebut
- Klien dapat meminta agar hasil kueri dikembalikan hanya jika kondisi yang ditentukan oleh header bersyarat terpenuhi
Caching dan permintaan Range
- Respons metode QUERY dapat di-cache, dan cache dapat digunakan untuk memenuhi permintaan QUERY berikutnya
- Cache key untuk permintaan QUERY harus mencakup body permintaan dan metadata terkait
- Cache dapat menghapus perbedaan yang secara semantik tidak penting untuk membuat cache key
- menghapus content encoding
- normalisasi menurut konvensi format yang ditunjukkan oleh suffix media subtype seperti
+json - normalisasi menurut makna body yang ditunjukkan oleh
Content-Type
- Transformasi ini hanya untuk pembuatan cache key dan tidak mengubah permintaan itu sendiri
- Klien dapat menandai lewat direktif cache
no-transformbahwa transformasi semacam ini tidak diinginkan, tetapi direktif ini bersifat advisory - Caching respons QUERY pada dasarnya lebih kompleks daripada GET
- Untuk menentukan cache key, seluruh body permintaan harus dibaca
- Jika respons QUERY memberi URI equivalent resource lewat Location, klien dapat beralih ke GET sesudahnya untuk menyederhanakan pemrosesan
- Makna Range Request pada QUERY sama seperti pada GET
- Satu-satunya range unit yang didefinisikan saat penulisan, yaitu Byte Range Request, bernilai kecil untuk hasil QUERY
- Dalam banyak kasus, format kueri itu sendiri menyediakan pembatasan hasil atau pagination, seperti
FETCH FIRST ... ROWS ONLYpada SQL, dan penggunaan fitur bawaan seperti itu memang diharapkan
Header respons Accept-Query
- Header respons Accept-Query secara langsung memberi tahu bahwa resource mendukung metode QUERY dan mengidentifikasi media type format kueri yang dapat digunakan
- Accept-Query adalah daftar media range yang menggunakan sintaks Structured Fields
- Media range dinyatakan sebagai List Structured Header Field dari Token atau String yang berisi nilai media range tanpa parameter
- Parameter media type dipetakan ke Structured Field Parameters
- Pilihan antara String dan Token tidak penting secara semantik
- Penerima dapat mengubah Token menjadi String, tetapi tidak boleh memprosesnya berbeda berdasarkan tipe yang diterima
- Media type tidak selalu dipetakan tepat ke Token, dan bila angka di awal diizinkan maka format String harus digunakan
- Wildcard yang didukung hanya
*/*atauxxxx/* - Urutan tipe yang tercantum dalam nilai field tidak penting
- Nilai Accept-Query berlaku untuk semua URI di server yang berbagi path yang sama, dan query component diabaikan
- Jika permintaan ke resource yang sama mengembalikan nilai Accept-Query yang berbeda, nilai fresh yang diterima paling baru yang digunakan
- Contohnya sebagai berikut
Accept-Query: "application/jsonpath", application/sql;charset="UTF-8"
- Accept-Query terlihat mirip dengan
Accept, tetapi karena merupakan Structured Field, pemrosesannya harus mengikuti aturan Structured Fields dari RFC 9651
Pertimbangan keamanan dan CORS
- QUERY mengikuti semua pertimbangan keamanan umum untuk metode HTTP sebagaimana didefinisikan di RFC 9110
- QUERY dapat digunakan sebagai alternatif terhadap cara menaruh informasi permintaan di query component URI
- Karena URI lebih mungkin tercatat di log atau diproses perantara dibanding body permintaan, QUERY dapat menjadi alasan untuk dipilih daripada GET saat kueri memuat informasi sensitif
- Saat server membuat resource sementara yang merepresentasikan hasil QUERY dan memberinya URI, jika body permintaan asli berisi informasi sensitif yang tidak boleh tercatat di log, bagian sensitif itu tidak boleh dimasukkan ke URI tersebut
- Jika cache menormalisasi body QUERY secara keliru atau dengan cara yang sangat berbeda dari cara resource memprosesnya, respons yang salah bisa dikembalikan sebagai false positive
- Permintaan QUERY dari user agent yang mengimplementasikan CORS memerlukan permintaan preflight
- QUERY tidak termasuk dalam kumpulan CORS-safelisted methods
Registrasi IANA dan pemilihan nama metode
- IANA menambahkan metode QUERY ke HTTP Method Registry
- Method Name:
QUERY - Safe:
yes - Idempotent:
yes - Specification: RFC 10008 Section 2
- Method Name:
- IANA menambahkan field Accept-Query ke HTTP Field Name Registry
- Field Name:
Accept-Query - Status:
permanent - Structured Type:
List
- Field Name:
- Di HTTP Method Registry sudah ada
PROPFIND,REPORT, danSEARCHyang memiliki sifat safe dan idempotent - Pada tahap awal,
SEARCHdigunakan, tetapi nama metode finalnya menjadi QUERY - Alasan QUERY dipilih adalah sebagai berikut
- Alternatif-alternatifnya menggunakan media type umum
application/xmldi body permintaan dan makna permintaan sepenuhnya bergantung pada body - Alternatif-alternatif itu semuanya berasal dari aktivitas WebDAV
QUERYmenangkap dengan baik hubungan dengan query component pada URI
- Alternatif-alternatifnya menggunakan media type umum
1 komentar
Komentar Hacker News
Akan lebih meyakinkan kalau ada contoh motivasi yang kuat, tetapi contoh yang dipakai terlalu mudah diekspresikan dengan GET sehingga malah terasa mengaburkan
Bahkan jika membayangkan QUERY yang memasukkan struktur filter JSON besar atau input gambar ke dalam body permintaan, tetap terasa sangat aneh bahwa body permintaan menjadi bagian dari kunci cache. Itu menciptakan kunci cache tak terbatas yang dikendalikan pengguna, dan strategi caching umum pada praktiknya hanya bisa membandingkan body permintaan per bit atau melakukan hash, jadi dalam situasi jahat cache menjadi sangat mudah di-invalidasi
Jika membuat layanan yang memerlukan pemfilteran kompleks atau input kompleks seperti gambar, kemungkinan caching akan berada jauh dari lapisan HTTP. Misalnya, bisa memakai kunci seperti kolom data individual dari join, atau embedding yang dikunci dengan perceptual hash dari input gambar yang sudah didekode, sehingga tidak bergantung pada representasi bit yang persis sama di wire
Saya tidak paham mengapa hal seperti ini harus dipaksakan ditangkap dengan cara umum. Menurut saya jauh lebih baik mengekspresikan semantik caching pada POST dengan header baru seperti
"Vary: request-body". Itu sepenuhnya kompatibel ke belakang, dan selain untuk 0,1% kasus CDN yang mungkin merasa perilaku ini berguna, sisanya bisa saja mengabaikannyaSaya tidak terpikir serangan terkait caching yang tidak berlaku sama juga untuk parameter query. Kalau ingin membanjiri cache, membuat parameter query unik 30 karakter sama mudahnya dengan membuat body permintaan 30 MB
Secara realistis, sistem untuk internet publik akan memakai hash kriptografis sebagai kunci cache agar ukurannya selalu tetap. Kunci cache juga sudah mencakup URL yang bisa sangat panjang dan sekumpulan nilai header arbitrer
GET dengan parameter query pun sudah opak dan membuat invalidasi cache jadi mudah
Namun kalau menaruh QUERY di depan POST, rasanya akan lebih baik. Karena itu bukan lagi request yang sama dengan flag aman, melainkan tipe request yang berbeda
Saya penasaran apakah form HTML akan menambahkan dukungan QUERY
Karena QUERY harus idempoten, ini bisa menghindari peringatan kirim ulang yang menjengkelkan saat menyegarkan halaman hasil submit form POST
Jika
method=QUERYditambahkan, keanehan ini hanya akan punya satu varian baru lagiUntuk yang masih ingin berpura-pura kita hidup di abad lalu: https://www.rfc-editor.org/rfc/rfc10008.txt
“Usulan untuk menambahkan body ke request GET telah ditinjau mendalam oleh kelompok kerja IETF, tetapi pada akhirnya diputuskan untuk membuat metode QUERY yang baru. Keputusan membuat metode terpisah didorong oleh masalah interoperabilitas historis dan kepatuhan ketat terhadap definisi arsitektur inti HTTP”
Tetapi saya sudah bertahun-tahun mengirim body permintaan dengan metode GET
fetch, misalnya, seperti ituhttps://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/U...
“GET request tidak bisa menyertakan body”
Bisa juga menimbulkan masalah aneh karena caching transparan
Mengejutkan bahwa sekarang kita sudah sampai di nomor RFC 5 digit
Seseorang membuat taruhan ambigu soal kapan RFC 10000 akan diterbitkan, lalu penomoran melompat langsung dari 9998 ke 10008. Tidak ada yang menang
https://manifold.markets/CollectedOverSpread/when-will-rfc-1...
Jadinya seperti kalau ingin menanyakan hasil pencarian dalam HTTP, pakailah metode QUERY, dan jangan tambahkan parameter query
Namanya membingungkan. Istilah
querysudah dipakai untuk merujuk ke permintaan HTTP secara umumSaya juga bingung hanya dari melihat judul RFC-nya
querydipakai untuk merujuk ke permintaan HTTP secara umum? Secara lisan orang kadang menyebut request GET sebagai query, tetapi untuk POST, PUT, DELETE jelas tidak pernahEdit: oh, ternyata QUERY dinyatakan sebagai metode “aman” tanpa efek samping demi memungkinkan caching. Saya keliru
Jika ini benar-benar sampai menggantikan request GET dengan query string di dunia nyata, saya sangat berharap bookmark browser mendukung pelestarian parameter permintaan
Saya tahu ini di luar cakupan RFC ini, tetapi hal bagusnya adalah ini bisa dengan mudah diperluas agar JS
EventSourcejuga bisa dipakai untuk query AI streamingKarena permintaan butuh body, semua orang akhirnya memakai POST, dan hasil streaming sering memakai protokol
text/event-streamdi respons. Tetapi sebenarnya tidak ada perubahan state, jadi secara teknis kurang pas, danEventSourcetetap keras kepala hanya bisa memakai GET. Akibatnya banyak API mengimplementasikan ulang fungsi yang sama dengan parser sendiriSaat melihat
GET: Content (body) "no defined semantics", saya sempat berpikir mungkin tidak masalah mengizinkan body pada metode GET, tetapi menurut spesifikasi aslinya body GET memang harus diabaikan sepenuhnyaSelain itu, caching juga bisa rusak jika bagian penting dari request dimasukkan ke dalam body yang dibuang
Jika menambahkan parameter body ke GET, dua request dengan URI yang sama tidak lagi bisa diperlakukan sebagai menunjuk hal yang sama, sehingga membongkar batasan metode ini