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.
GET dengan body tidak pernah aman
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.POST untuk pencarian: berfungsi, tapi mengorbankan terlalu banyak
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: body seperti POST, jaminan seperti GET
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": "smith@example.org" } ]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.
Safe, idempotent, cacheable — apa yang dibeli oleh tiap jaminan
Ketiga kata itu bukan hiasan; masing-masing membuka perilaku spesifik dalam mesin di antara klien dan server Anda.
- Safe berarti intermediary dan klien tahu request bersifat read-only, sehingga prefetching, mengikuti tautan, dan retry otomatis semuanya sah — kebebasan yang sama yang sudah mereka berikan pada GET.
- Idempotent berarti request yang gagal di tengah jalan bisa di-retry otomatis, karena mengulanginya memberi efek yang sama seperti mengirimnya sekali. Ini jaminan yang tak pernah bisa diberikan POST untuk pencarian.
- Cacheable berarti shared cache boleh menyimpan respons dan menyajikannya untuk query identik berikutnya, memangkas beban origin pada pencarian populer tanpa Anda membangun lapisan cache khusus.
Kunci cache berada di dalam body
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.
Tiga cara menjalankan pencarian yang sama
| 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) |
Bisakah Anda memakainya sekarang?
QUERY adalah Proposed Standard, bukan janji masa depan, tetapi tooling masih menyusul — jadi jawaban jujurnya: di sisi server, makin bisa; di browser, belum.
- Stack .NET 10 dan ASP.NET Core 10 menyediakan dukungan kelas satu: HttpMethod.Query di klien dan HttpMethods.Query dengan helper IsQuery di server, sehingga Anda bisa merutekan request QUERY hari ini.
- Browser belum bisa mengirim QUERY dari fetch atau XMLHttpRequest, dan MDN belum punya halaman QUERY khusus — hanya sebuah tracking issue — jadi klien web publik masih butuh fallback.
- Pola pragmatis untuk sekarang adalah QUERY antar-service dengan endpoint pencarian POST paralel untuk browser, berbagi handler yang sama, sampai dukungan klien tiba.
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.

