Satu alamat di server bisa mengirim data yang sama dalam beberapa bentuk: JSON buat aplikasi, HTML buat browser. Content negotiation adalah cara client (browser atau aplikasi yang mengirim request) dan server sepakat bentuk mana yang dikirim: client menyebut kesukaannya lewat header, server memilih yang paling cocok dari yang dia punya.
🧪 Tebakan cepat: client mengirim
Accept: text/html;q=0. Artinya dia sedikit suka HTML, atau menolak HTML? Tebak dulu, jawabannya ada di bagian "Nilai q: seberapa suka".
Client minta, server memilih
GET /users/42 HTTP/1.1
Accept: text/html;q=0.5, application/json
HTTP/1.1 200 OK
Content-Type: application/json
Vary: Accept
{"id": 42, "nama": "Budi"}
Acceptadalah header request: daftar format yang client mau terima, dipisah koma.text/htmldanapplication/jsonadalah MIME type, nama format yang ditulisjenis/subjenis.;q=0.5adalah nilai kesukaan untuktext/html.application/jsongak punyaq, jadi nilainya1.Content-Type: application/jsonadalah jawaban server: "yang kukirim ini JSON".Vary: Acceptdibahas di bagian terakhir.
Hasilnya: JSON bernilai 1, HTML 0.5, jadi server mengirim JSON.
Nilai q: seberapa suka
q adalah angka dari 0 sampai 1. Makin besar, makin disukai. Tanpa q, nilainya 1.
- Yang menentukan nilai
q, bukan urutan penulisan.text/plain;q=0.3, text/html;q=0.9, application/jsonartinya JSON, lalu HTML, lalu teks biasa. q=0artinya menolak: "jangan kirim format ini". Itu jawaban tebakannya.- Server cuma memilih dari format yang dia punya, yang nilainya paling tinggi. Kalau seri, server memakai urutan kesukaannya sendiri.
- Kalau gak ada yang cocok, server boleh membalas
406 Not Acceptable, atau mengirim format bawaannya saja.
Tanda bintang: format apa saja
*/* cocok dengan format apa pun. text/* cocok dengan semua format berjenis text, misalnya text/html dan text/plain, tapi gak dengan application/json. Browser biasanya mengirim kayak text/html, */*;q=0.8: "paling suka HTML, yang lain juga boleh".
Bahasa dan kompresi juga ditawar
| Client minta lewat | Contoh | Server jawab lewat |
|---|---|---|
Accept |
application/json |
Content-Type |
Accept-Language |
id, en;q=0.5 |
Content-Language |
Accept-Encoding |
gzip, br |
Content-Encoding |
Accept-Encoding menyebut cara kompres (memampatkan data) yang bisa dibuka browser. Aturan q-nya sama.
Vary: biar cache gak ketuker
Cache adalah salinan response yang disimpan, di browser atau di CDN (server perantara di banyak kota), supaya request berikutnya gak perlu sampai ke server asli. Tanpa Vary, cache cuma melihat URL-nya, jadi response JSON untuk /users/42 bisa ikut dikirim ke browser yang minta HTML. Vary: Accept artinya "simpan salinan terpisah untuk tiap nilai Accept". Untuk bahasa, tulis Vary: Accept-Language.
⚠️ Jebakan yang sering ketemu
AcceptdanContent-Typeketuker.Acceptada di request: format yang client mau terima.Content-Typemenyebut format body yang sedang dikirim.- Baris yang lebih spesifik didahulukan. Di HTTP sungguhan, kalau satu format cocok dengan beberapa baris, baris yang paling spesifik yang berlaku:
text/html;q=0, */*artinya "apa saja boleh, kecuali HTML". Latihan di sini cukup mengambilqtertinggi, karena contoh-contohnya gak pernah bentrok dengan aturan ini.
TL;DR: Client menyebut format yang dia mau lewat Accept (bahasa lewat Accept-Language, kompresi lewat Accept-Encoding), boleh dengan nilai q dari 0 sampai 1: tanpa q berarti 1, q=0 berarti menolak. Server memilih format bernilai tertinggi yang dia punya dan menyebutnya di Content-Type, atau membalas 406. */* dan text/* cocok dengan banyak format. Vary bikin cache menyimpan salinan terpisah per pilihan.