Content Negotiation — Web Fundamentals

Content negotiation adalah mekanisme HTTP yang memungkinkan satu URL menyajikan representasi berbeda dari resource yang sama — tergantung kesukaan client. Endpo

Content negotiation adalah mekanisme HTTP yang memungkinkan satu URL menyajikan representasi berbeda dari resource yang sama — tergantung kesukaan client. Endpoint /users/42 bisa mengembalikan JSON untuk aplikasi mobile, HTML untuk browser, atau XML untuk partner legacy — semuanya dari URL yang sama.

Mengapa perlu content negotiation? Bayangkan API yang dipakai banyak client berbeda: browser ingin HTML, aplikasi mobile ingin JSON, third-party service ingin XML. Daripada membuat tiga URL terpisah, kita biarkan client mengatakan "saya mau format X" lewat header — server pilih yang paling cocok.

Header request yang digunakan client:

Header Fungsi Contoh
Accept Format konten yang diinginkan application/json, text/html;q=0.9
Accept-Language Bahasa yang diinginkan id-ID, en-US;q=0.8
Accept-Encoding Kompresi yang didukung gzip, br, deflate
Accept-Charset Character set (jarang dipakai sekarang) utf-8

Quality values (q-factor): Client bisa memberi bobot preferensi dengan q=. Nilai antara 0 dan 1 — semakin tinggi, semakin disukai. Default q=1.

Accept: application/json;q=1.0, application/xml;q=0.8, text/html;q=0.5

Artinya: "saya paling suka JSON, XML masih oke, HTML sebagai pilihan terakhir." Server memilih format dengan q tertinggi yang bisa ia hasilkan.

Contoh negosiasi bahasa:

Accept-Language: id-ID, id;q=0.9, en-US;q=0.7, en;q=0.5

Client bilang: "Prioritas bahasa Indonesia Indonesia, lalu Indonesia umum, kalau tidak ada baru English US, terakhir English apapun."

Server membalas dengan Content-Type:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Language: id-ID

{"id": 42, "name": "Budi"}

Server memberi tahu: "Ini yang saya pilihkan untukmu."

Ketika tidak ada yang cocok: 406 Not Acceptable Kalau client minta format yang tidak bisa dihasilkan server, dan server ingin strict, ia boleh membalas 406:

GET /users/42
Accept: application/x-yaml

HTTP/1.1 406 Not Acceptable
Content-Type: application/json
{"error": "Only JSON and HTML are supported"}

Dalam praktik, banyak API memilih fallback ke default daripada 406, untuk pengalaman yang lebih ramah.

Vary header — penting untuk cache: Kalau satu URL bisa mengembalikan banyak representasi, cache (CDN, proxy) harus tahu: "response ini tergantung header apa?" Itulah gunanya Vary.

HTTP/1.1 200 OK
Content-Type: application/json
Vary: Accept, Accept-Language

Artinya: "Cache response ini terpisah untuk kombinasi Accept dan Accept-Language yang berbeda." Tanpa Vary, CDN bisa menyajikan JSON ke user yang sebenarnya minta HTML — bug yang sulit dilacak.

Implementasi di Laravel:

Route::get("/users/{id}", function ($id, Request $request) {
    $user = User::findOrFail($id);

    if ($request->wantsJson()) {
        return response()->json($user);
    }

    if ($request->accepts("text/html")) {
        return view("users.show", ["user" => $user]);
    }

    abort(406);
});

Implementasi di Node.js (Express):

app.get("/users/:id", (req, res) => {
  const user = getUser(req.params.id);

  res.format({
    "application/json": () => res.json(user),
    "text/html": () => res.render("user", { user }),
    default: () => res.status(406).send("Not Acceptable"),
  });
});

Parsing Accept di tangan — contoh JavaScript:

function parseAccept(header) {
  return header.split(",").map((item) => {
    const [type, ...params] = item.trim().split(";");
    const q = params.find((p) => p.trim().startsWith("q="));
    return {
      type: type.trim(),
      quality: q ? parseFloat(q.split("=")[1]) : 1.0,
    };
  }).sort((a, b) => b.quality - a.quality);
}

parseAccept("text/html, application/json;q=0.9, */*;q=0.1");
// [{type:"text/html", quality:1}, {type:"application/json", quality:0.9}, ...]

Wildcard di Accept:

Biasanya browser mengirim sesuatu seperti text/html, */*;q=0.8 — berarti "saya prioritas HTML, tapi apapun oke."

Tips praktis content negotiation:

Content negotiation adalah contoh elegan bagaimana HTTP memungkinkan satu resource tampil berbeda untuk kebutuhan berbeda — tanpa duplikasi endpoint.

Yang akan kamu pelajari