Dalam satu kalimat
Pesan HTTP adalah sebuah blok teks biasa terformat yang saling dipertukarkan oleh browser dan server web, berfungsi sebagai gabungan dari label pengiriman, buku panduan, dan isi paket untuk setiap interaksi di web.
Masalah yang dipecahkannya
Di masa-masa purba internet awal 1990-an, semuanya masih sederhana. Sebuah browser perlu cara untuk bertanya pada server, "Woy, boleh minta file science.html itu nggak?" dan server perlu cara untuk menjawab, "Boleh, nih," atau "Maaf, nggak ketemu." Percakapan ini butuh aturan—sebuah protokol. Protokol itulah yang menjadi HTTP, Hypertext Transfer Protocol.
"Masalah" yang dipecahkannya adalah menciptakan bahasa universal yang tidak ambigu untuk web. Tanpa format standar, satu server mungkin mengharapkan permintaan dalam satu baris, sementara yang lain mungkin butuh pantun. Bakal kacau balau. HTTP/0.9 versi awal sangatlah sederhana: GET /halaman-yang-kuinginkan.html. Server hanya akan langsung mengirimkan balik HTML-nya.
Tapi web tidak selamanya sederhana. Kita perlu mengirim data ke server untuk mengisi formulir. Kita perlu menangani berbagai jenis konten seperti gambar dan, belakangan, JSON. Kita butuh keamanan, caching, dan cara bagi browser untuk mendeskripsikan dirinya sendiri. Permintaan satu baris yang simpel itu berevolusi menjadi "pesan" multi-bagian yang terstruktur dengan baris-awal, blok metadata (header), dan body opsional untuk payload sebenarnya. Merakit pesan-pesan ini secara manual menjadi keahlian fundamental bagi siapa pun yang bekerja langsung dengan infrastruktur web, API, atau keamanan, memecahkan masalah tentang bagaimana cara melakukan urusan yang semakin kompleks melalui dialog permintaan-respons sederhana di web.
Cara kerjanya di balik layar
Pada dasarnya, pesan HTTP itu cuma teks biasa. Kamu benar-benar bisa mengetiknya di terminal lalu mengirimkannya ke server kalau kamu niat. Teks ini dibagi menjadi tiga bagian: baris-awal (start-line), blok header, dan body opsional, semuanya dipisahkan oleh pemisah baris spesifik (\r\n, atau CRLF singkatan dari "Carriage Return, Line Feed").
Ada dua jenis pesan: permintaan (request, dari klien ke server) dan respons (response, dari server ke klien). Keduanya terlihat hampir identik tetapi memiliki baris pertama yang berbeda.
Anatomi Pesan Request
Ini adalah saat browsermu meminta sesuatu.
GET /documentation/guides/http-builder HTTP/1.1
Host: flowing.dev
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/117.0
Accept: text/html,*/*
Accept-Language: en-US,en;q=0.5
Connection: keep-alive
<-- Body seharusnya di sini, tapi request GET biasanya nggak punya -->
Start-Line:
GET /documentation/guides/http-builder HTTP/1.1GET: method (atau verb) HTTP. Ini adalah apa yang ingin kamu lakukan.GETmengambil data,POSTmengirim data baru,PUTmemperbarui data yang ada,DELETEmenghapus data./documentation/...: Path resource. Digabungkan dengan headerHost, ini membentuk URL lengkap.HTTP/1.1: Versi protokol.
Header: Daftar pasangan kunci-nilai yang menyediakan metadata krusial tentang permintaan.
Host: flowing.dev: Untuk siapa permintaan ini? Header ini wajib di HTTP/1.1.User-Agent: Mozilla/5.0...: Siapa yang mengirim permintaan ini? Browser mengidentifikasi dirinya.Accept: text/html,*/*: Format respons seperti apa yang bisa saya mengerti? Di sini, browser lebih suka HTML tetapi akan menerima apa saja.
Baris Kosong: Setelah header terakhir, satu baris kosong (
\r\n) menandakan "header sudah selesai, selanjutnya adalah body." Ini tidak bisa ditawar. Menghilangkannya akan merusak segalanya.Body: Payload data yang sebenarnya. Untuk request
GET, biasanya kosong. UntukPOSTatauPUT, di sinilah data formulir atau payload JSON-mu berada.
Anatomi Pesan Respons
Ini adalah saat server membalas request.
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 15328
Server: Vercel
Date: Mon, 25 Sep 2023 10:30:00 GMT
Cache-Control: public, max-age=0, must-revalidate
<!DOCTYPE html>
<html>
<head>...</head>
<body>...</body>
</html>
Status-Line:
HTTP/1.1 200 OKHTTP/1.1: Versi protokol, sama seperti request.200: Status Code. Angka tiga digit yang merangkum hasilnya.2xxberarti sukses,3xxberarti pengalihan (redirection),4xxberarti kamu (klien) yang salah, dan5xxberarti aku (server) yang salah.OK: Reason Phrase. Ringkasan status code yang bisa dibaca manusia.
Header: Metadata tentang respons.
Content-Type: text/html: "Body yang kukirimkan ini adalah HTML." Ini sangat penting agar browser tahu cara me-render payload.Content-Length: 15328: "Body ini panjangnya persis 15.328 byte."Set-Cookie: ...: Cara server memberitahu browser untuk menyimpan cookie.Cache-Control: ...: Instruksi tentang bagaimana browser atau proxy perantara harus melakukan cache terhadap respons ini.
Body: Resource yang diminta klien—HTML, CSS, objek JSON, data gambar, dll.
Pesta Pora Body: Mengenkode Payload
Ketika sebuah request memiliki body, ia memerlukan header Content-Type untuk menjelaskan formatnya. Tiga yang paling umum adalah:
application/x-www-form-urlencoded: Format default untuk formulir HTML jadul. Isinya hanyalah query string di dalam body.name=Grace+Hopper&title=Rear+Admiralapplication/json: Raja para API modern. Body-nya adalah string JSON.{ "name": "Grace Hopper", "title": "Rear Admiral" }multipart/form-data: Format untuk mengirim formulir yang menyertakan unggahan file. Ini seperti pesan di dalam pesan. Body dipecah menjadi beberapa bagian, masing-masing dipisahkan oleh string "boundary". Setiap bagian dapat memiliki header mini-nya sendiri (sepertiContent-DispositiondanContent-Type) dan kontennya sendiri.POST /profiles/edit HTTP/1.1 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW ----WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="username" ada_lovelace ----WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="avatar"; filename="portrait.jpg" Content-Type: image/jpeg <...data biner mentah dari gambar ada di sini...> ----WebKitFormBoundary7MA4YWxkTrZu0gW--
Cerita dari dunia nyata
Kasus Content-Type yang Lenyap
Seorang developer sedang membangun REST API pertamanya. Endpoint-nya seharusnya menerima payload JSON untuk membuat pengguna baru. Dia menulis kode server dan mengujinya dengan tool baris perintah, mengirim objek JSON yang valid banget. Tapi server terus merespons dengan 400 Bad Request. Dia menghabiskan dua jam menatap JSON-nya, yakin ada koma yang terlewat. Dalam keputusasaan, dia meminta bantuan dev senior. Dev senior itu melihat request-nya sekali dan bertanya, "Di mana header Content-Type-mu?" Si developer telah mengirim data JSON, tetapi dia tidak pernah memberi tahu server bahwa itu adalah JSON. Framework di server, yang ngiranya bakal dapat x-www-form-urlencoded (format default), mencoba mem-parsing JSON tadi sebagai query string, gagal total, dan akhirnya menolak permintaan itu.
Pelajaran: Body sebuah pesan tidak ada artinya tanpa header Content-Type untuk memberinya konteks. Kamu harus memberi label pada paketmu dengan benar.
Kisruh Multipart
Sebuah tim sedang membuat halaman "pengaturan" di mana pengguna bisa mengubah nama mereka dan secara opsional mengunggah gambar profil baru. Dev frontend junior mengimplementasikannya dengan dua panggilan API terpisah: request PUT dengan nama pengguna dalam body JSON, dan kemudian, jika ada gambar yang dipilih, request POST dengan data gambar. Itu berhasil, tapi kaku, ribet, dan menciptakan race condition. Bagaimana jika perubahan nama berhasil tetapi unggahan gambar gagal? Pengguna akan berada dalam keadaan yang tidak konsisten. Seorang engineer backend melihat lalu lintas jaringan dan menariknya ke samping. "Ini adalah kasus penggunaan yang sempurna untuk multipart/form-data," jelasnya. Mereka me-refactor kode untuk membangun satu request POST tunggal dengan dua bagian: satu untuk field nama dan satu untuk file gambar. Ini menyederhanakan kode dan membuat seluruh pembaruan menjadi operasi atomik.
Pelajaran: multipart bukan hanya untuk file. Ini untuk mengirim sekantong data campuran—field teks, file, jenis konten yang berbeda—dalam satu request yang andal.
Hantu di dalam Cache
Sebuah situs e-commerce sedang mengadakan flash sale, tetapi pengguna mengeluh bahwa mereka melihat harga yang usang. Tim ops bingung; caching di sisi server mereka dikonfigurasi dengan benar. Seorang ahli performa web dipanggil. Alih-alih menggunakan dev tools browser, dia menggunakan tool untuk memeriksa respons HTTP mentah untuk halaman produk. Dia langsung menemukan biang keladinya. Sebuah load balancer yang salah konfigurasi di depan server web menyuntikkan headernya sendiri Cache-Control: public, max-age=3600, menimpa header Cache-Control: no-cache yang diinginkan server. Header nakal ini memberitahu browser dan CDN untuk melakukan cache harga selama satu jam, tidak peduli apa kata server aplikasi.
Pelajaran: Pesan HTTP mentah adalah sumber kebenaran tertinggi. Tool tingkat tinggi terkadang dapat menyembunyikan atau salah menafsirkan detail yang padahal jelas banget di dalam teks itu sendiri.
Kesalahan dan jebakan umum
- Lupa baris kosong. Pesan HTTP harus memiliki CRLF (
\r\n) antara header dan body. Jika hilang, parser akan menganggap body-mu hanyalah header lain yang salah format dan request akan gagal. Content-Lengthyang tidak cocok. Jika kamu mendeklarasikan headerContent-Length, nilainya harus ukuran byte yang persis sama dengan body. Jika terlalu kecil, datamu akan terpotong. Jika terlalu besar, server akan menunggu selamanya untuk byte yang tidak pernah datang.Content-Typeyang salah. Mengirim body JSON tetapi melabelinya sebagaitext/plainadalah resep jitu untuk dapat eror4xx. Header dan body harus sinkron.- CRLF vs. LF. Spesifikasi resmi menuntut
\r\nuntuk pemisah baris. Sebagian besar server modern cukup toleran dan akan menerima\n(Line Feed) sederhana. Namun, mengandalkan ini dapat menyebabkan request-mu gagal pada server, proxy, atau firewall yang lebih tua dan lebih kaku. - Encoding karakter khusus. Lupa melakukan URL-encode pada data dalam query string atau body
x-www-form-urlencodedadalah bug klasik. Spasi harus menjadi%20,&harus menjadi%26, dan seterusnya, atau kamu berisiko merusak datamu.
Kenapa Ini Wajib Ada di Radarmu
Sebagian besar waktu, browser, framework, atau library-mu (seperti axios atau requests) menangani detail rumit dalam membangun pesan HTTP untukmu. Tetapi kamu harus tahu cara melakukannya secara manual ketika:
- Kamu sedang deep-debugging. Ketika panggilan API tidak berfungsi dan pesan error-nya tidak jelas, memeriksa atau membuat ulang pesan HTTP mentah adalah wasit terakhir. Ini memungkinkanmu melihat persis apa yang dikirimkan lewat kabel, bebas dari abstraksi apa pun.
- Kamu sedang membangun atau menguji API. Memahami struktur pesan adalah fundamental untuk merancang endpoint API yang baik dan menulis tes integrasi yang efektif. Para penguji keamanan menghabiskan hari-hari mereka merakit pesan yang sengaja dibuat cacat untuk menemukan kerentanan.
- Kamu sedang melakukan scraping sebuah situs web. Untuk berhasil meniru browser sungguhan dan melewati langkah-langkah anti-bot, kamu sering kali perlu membuat request dengan kombinasi header yang sangat spesifik (
User-Agent,Referer,Accept-*, dll.). - Kamu sedang bekerja dengan webhook. Ketika aplikasimu menerima webhook dari layanan seperti Stripe atau GitHub, kamu berada di pihak penerima request HTTP mentah. Kamu perlu mem-parsing headernya (misalnya, untuk signature keamanan) dan body-nya untuk menindaklanjuti event tersebut.
Mengetahui cara merakit pesan HTTP dari nol itu seperti montir yang paham cara kerja mesin pembakaran internal. Kamu tidak melakukannya setiap hari, tapi saat ada yang rusak, pengetahuan fundamental itu jadi tak ternilai harganya.
Gali lebih dalam
- An overview of HTTP on MDN - Tempat terbaik untuk memulai panduan tingkat tinggi yang mudah dibaca.
- RFC 9112: HTTP/1.1 - Spesifikasi teknis utama untuk sintaks pesan HTTP/1.1. Padat tapi definitif.
- HTTP headers on MDN - Referensi komprehensif dan dapat dicari untuk setiap header HTTP standar.
- POST on MDN - Panduan praktis yang mencakup detail tentang berbagai body
Content-Typeuntuk request POST. - Wikipedia: Hypertext Transfer Protocol - Tinjauan yang solid tentang sejarah dan konteks HTTP.