Metode HTTP QUERY: GET Aman dengan Body (RFC 10008)

Foto oleh Taylor Vick on Unsplash
QUERY adalah metode request HTTP, distandarkan dalam RFC 10008 pada Juni 2026, yang meminta server memproses konten yang dibawa di body request lalu mengembalikan hasilnya. Ia pada dasarnya adalah GET aman dengan body: parameternya berjalan di body alih-alih di URI, tetapi request-nya mempertahankan jaminan read-only milik GET. Ia didefinisikan oleh IETF HTTP Working Group dalam draft bernama draft-ietf-httpbis-safe-method-w-body.
Ya. RFC 10008 menyatakan respons QUERY bersifat cacheable dan sebuah cache boleh memakainya ulang untuk melayani request QUERY berikutnya. Perbedaan utama dari GET adalah kunci cache harus menyertakan body request dan metadata terkait, bukan hanya URL, karena query-nya sendiri berada di body. Server juga bisa mengembalikan header Content-Location yang menunjuk ke resource hasil yang dapat diambil via GET untuk caching konvensional.
GET secara teknis bisa membawa body, tetapi RFC 9110 menyatakan konten dalam request GET tidak memiliki semantik yang terdefinisi secara umum dan bahkan bisa ditolak sebagai potensi serangan request smuggling. QUERY dibuat justru untuk menghapus ambiguitas itu: ia secara eksplisit mendefinisikan bahwa body request adalah query-nya. Jadi QUERY memberi cara yang portabel, terspesifikasi jelas, dan interoperabel untuk mengirim body pada request yang aman — sesuatu yang tak pernah dimiliki GET.
Sebagian. Framework server mulai mendukungnya: .NET 10 dan ASP.NET Core 10 mengekspos HttpMethod.Query di klien dan HttpMethods.Query dengan helper IsQuery di server. Namun browser belum bisa mengirim QUERY via fetch atau XMLHttpRequest, dan MDN belum punya halaman khusus untuknya. Untuk sekarang QUERY paling cocok untuk API antar-service, dengan endpoint POST paralel untuk klien publik dan browser.
POST berfungsi untuk body pencarian yang kompleks, tetapi ia tidak safe, tidak idempotent, dan tidak cacheable, sehingga proxy dan cache tidak bisa dengan aman me-retry atau memakai ulang responsnya. QUERY membawa body yang sama tetapi didefinisikan safe dan idempotent, sehingga request yang gagal bisa di-retry otomatis dan respons bisa di-cache. Pakai QUERY untuk pencarian read-only dan simpan POST untuk operasi yang benar-benar membuat atau mengubah state.

Foto oleh Taylor Vick on Unsplash
Ringkasan Utama
Metode HTTP QUERY, distandarkan dalam RFC 10008 pada Juni 2026, adalah request yang membawa body seperti POST tetapi bersifat safe, idempotent, dan cacheable seperti GET. Ia hadir agar API pencarian dan filter bisa mengirim query kompleks di dalam body tanpa menyalahgunakan GET-dengan-body atau kehilangan caching karena terpaksa memakai POST.
Setiap backend engineer pada akhirnya menabrak tembok yang sama: sebuah endpoint pencarian yang parameternya tidak lagi muat di dalam URL. Filter produk berfaset, seleksi field ala GraphQL, sebuah poligon geospasial — query-nya adalah data terstruktur, bukan segelintir parameter string. Secara historis HTTP hanya memberi dua pilihan buruk untuk itu, dan pada Juni 2026 IETF akhirnya merilis pilihan ketiga.
Pilihan ketiga itu adalah QUERY, diterbitkan sebagai RFC 10008, The HTTP QUERY Method. Ia lahir dari draft working-group bernama draft-ietf-httpbis-safe-method-w-body, dan nama draft itu adalah seluruh idenya dalam satu frasa: sebuah metode safe yang diizinkan membawa body. Sebelum membahas QUERY, ada baiknya tepat memahami mengapa dua pilihan lama menyakitkan.
Insting pertama adalah menaruh body pada GET, karena pencarian membaca data dan GET adalah metode baca. Spesifikasinya tidak setuju. RFC 9110, dokumen inti semantik HTTP, menyatakan terang-terangan bahwa konten yang diterima dalam request GET tidak memiliki semantik yang terdefinisi secara umum, tidak dapat mengubah makna atau target request, dan bisa membuat sebagian implementasi menolak request lalu menutup koneksi karena potensinya sebagai serangan request smuggling. Pada praktiknya: sebagian proxy diam-diam membuang body, dan sebagian lain memperlakukannya sebagai serangan. Request yang berperilaku berbeda tergantung intermediary yang dilewatinya bukanlah sesuatu yang layak dirilis.
GET /contacts?select=surname,givenname,email&limit=10&match=%22email%3D*%40example.*%22 HTTP/1.1
Host: example.org
# RFC 9110 §9.3.1: content in a GET request "has no generally
# defined semantics" and may be rejected as request smuggling.Maka kebanyakan dari kita beralih ke POST. Ia membawa body apa pun dan setiap klien serta proxy memahaminya. Masalahnya adalah makna POST. POST tidak safe, tidak idempotent, dan tidak cacheable — ia didefinisikan sebagai metode yang boleh mengubah state server. Definisi tunggal itu merenggut tiga hal konkret. Koneksi yang putus tidak bisa di-retry otomatis, karena tak ada jaminan percobaan pertama belum sempat mengubah sesuatu. CDN atau shared cache tidak bisa memakai ulang respons. Dan pembaca log Anda tidak bisa membedakan operasi tulis yang mengubah state dari operasi baca yang kebetulan membawa body besar. Anda akhirnya mendokumentasikan bahwa POST ini sebenarnya operasi baca dalam prosa yang tak akan pernah dibaca oleh cache atau proxy mana pun.
QUERY menyelesaikan ketegangan itu. RFC 10008 mendefinisikannya sebagai metode yang meminta resource target untuk memproses konten request yang disertakan secara safe dan idempotent lalu mengembalikan hasilnya. Kontennya — JSON, form-encoded, media type apa pun yang Anda deklarasikan — adalah query-nya. Karena metode ini didefinisikan safe, server berjanji request tidak mengubah state; karena idempotent, klien atau proxy boleh me-retry-nya setelah gangguan jaringan tanpa khawatir; dan karena responsnya cacheable, shared cache boleh memakainya ulang untuk request QUERY identik berikutnya. Ia secara harfiah adalah semantik baca GET dengan body request POST.
QUERY /contacts HTTP/1.1
Host: example.org
Content-Type: application/json
Accept: application/json
{ "select": ["surname","givenname","email"], "limit": 10, "match": "email=*@example.*" }
HTTP/1.1 200 OK
Content-Type: application/json
Content-Location: /contacts/responses/42
[ { "surname": "Smith", "givenname": "John", "email": "[email protected]" } ]Respons QUERY 2xx dapat membawa header Content-Location yang menunjuk ke sebuah resource hasil. RFC 10008 menggambarkannya sebagai klaim server bahwa klien boleh mengirim GET biasa ke URI tersebut untuk mengambil hasil yang sama — memberi Anda pegangan kedua yang cacheable via GET terhadap keluaran query bagi klien dan CDN yang hanya tahu cara meng-cache GET.
Ketiga kata itu bukan hiasan; masing-masing membuka perilaku spesifik dalam mesin di antara klien dan server Anda.
Ada satu hal yang benar-benar baru dan harus dilakukan dengan benar. Untuk GET, kunci cache adalah URI. Untuk QUERY, query-nya ada di body, jadi URI saja tidak cukup. RFC 10008 mensyaratkan kunci cache untuk request QUERY memasukkan konten request dan metadata terkait, bukan hanya URI target. Pada praktiknya sebuah cache harus mem-hash body — dengan menghormati content type dan header terkait — untuk membedakan dua pencarian berbeda yang dikirim ke path yang sama. Cache yang mendukung QUERY melakukannya untuk Anda; intinya, cache naif yang hanya berbasis URI akan dengan senang hati mengembalikan hasil yang salah jika Anda menempelkan QUERY tanpa dukungan.
Jangan aktifkan caching QUERY pada infrastruktur yang membuat kunci murni dari URL. Load balancer atau edge cache yang mengabaikan body akan menyajikan hasil satu pencarian untuk pencarian yang sama sekali berbeda yang dikirim ke path yang sama. Pastikan cache Anda memahami kunci cache QUERY yang menyertakan body sebelum mengaktifkan caching — jika tidak, biarkan mati dan perlakukan QUERY sebagai baca aman tanpa cache.
| Properti | GET (dengan body) | POST | QUERY |
|---|---|---|---|
| Body request | Tak terdefinisi oleh spec | Didukung penuh | Didefinisikan sebagai query |
| Safe (read-only) | Ya | Tidak | Ya |
| Idempotent / auto-retry | Ya | Tidak | Ya |
| Respons cacheable | Ya | Tidak | Ya |
| Jalan lintas proxy saat ini | Tidak — body sering dibuang | Ya | Mulai muncul (RFC 10008) |
QUERY adalah Proposed Standard, bukan janji masa depan, tetapi tooling masih menyusul — jadi jawaban jujurnya: di sisi server, makin bisa; di browser, belum.
Saya tidak akan mencabut POST /search yang masih berfungsi besok pagi. Tetapi jika Anda merancang API pencarian atau filter internal baru antar service yang Anda kendalikan, QUERY adalah metode yang tepat — ia akhirnya membuat operasi baca yang butuh body tetap menjadi operasi baca, sampai ke seluruh cache dan proxy di jalurnya. Gunakan di sana lebih dulu, simpan POST sebagai fallback untuk browser, dan biarkan ekosistem menyusul di sekitar Anda.