Pada chapter sebelumnya kita sudah melihat wujud mentah percakapan HTTP lewat curl -v. Sekarang saatnya membedah dua pesan tersebut secara sistematis: bagaimana sebuah request tersusun, bagaimana response menjawabnya, dan di mana letak setiap potong data. Pemahaman anatomi ini penting karena hampir semua pekerjaan PHP web — membaca form, memanggil API, men-debug respons — pada akhirnya adalah kegiatan membaca dan menyusun bagian-bagian pesan ini. Di akhir chapter kita juga akan membaca response HTTP langsung dari dalam skrip PHP.
Anatomi HTTP Request #
Setiap request HTTP, apa pun kliennya, tersusun dari empat bagian yang selalu berurutan. Perhatikan contoh request yang dikirim browser ketika pengguna men-submit form kontak:
POST /kontak HTTP/1.1
Host: www.tokobudi.example
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
nama=Budi&pesan=Halo+dari+BudiTabel berikut merinci peran setiap bagian:
| Bagian | Isi | Keterangan |
|---|---|---|
| Baris permintaan (request line) | POST /kontak HTTP/1.1 | method, path beserta query string, versi protokol |
| Header | Host, Content-Type, Content-Length, … | metadata satu baris per header, format Nama: nilai |
| Baris kosong | — | pemisah mutlak antara header dan body |
| Body | nama=Budi&pesan=... | data yang dikirim; boleh kosong |
Baris permintaan pada contoh di atas menyatakan bahwa klien meminta method POST ke path /kontak menggunakan protokol HTTP/1.1. Header Host wajib ada pada HTTP/1.1 karena satu server bisa melayani banyak domain. Header Content-Type memberi tahu format body — pada form HTML biasa, datanya di-encode seperti query string (nama=Budi&pesan=...). Terakhir, Content-Length menyatakan panjang body dalam byte, sehingga server tahu kapan data selesai.
Anatomi HTTP Response #
Response memiliki struktur kembar: baris status menggantikan baris permintaan, disusul header, baris kosong, lalu body. Contoh jawaban dari request di atas:
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 54
<html><body><h1>Terima kasih, Budi!</h1></body></html>Baris pertama (HTTP/1.1 200 OK) memberi tahu versi protokol, kode status 200, dan frasa alasan OK — inilah bagian yang dibaca browser untuk menentukan keberhasilan request. Header Content-Type menyatakan bahwa body adalah HTML, dan Content-Length menghitung panjang body dalam byte. Body adalah konten yang sebenarnya dirender browser: markup HTML pada contoh ini.
Karena strukturnya berbasis teks, kita bisa menyusun response yang sah secara programatik dengan operasi string biasa:
<?php
function buatResponseMentah(string $barisStatus, array $headers, string $body): string
{
$bagian = [$barisStatus];
foreach ($headers as $nama => $nilai) {
$bagian[] = $nama . ": " . $nilai;
}
return implode("\r\n", $bagian) . "\r\n\r\n" . $body;
}
$body = "Halo, Budi!\nSelamat belajar.";
echo buatResponseMentah(
"HTTP/1.1 200 OK",
[
"Content-Type" => "text/plain; charset=UTF-8",
"Content-Length" => strlen($body),
],
$body,
);Output yang Dihasilkan:
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 28
Halo, Budi!
Selamat belajar.Mari kita telaah kode di atas baris per baris:
- Baris 3-12 (
function buatResponseMentah(...)): fungsi ini menerima baris status, daftar header sebagai array asosiatif, dan body, lalu mengembalikan satu pesan response utuh. - Baris 10 (
implode("\r\n", ...)): setiap baris pesan dipisah pasangan CRLF sesuai aturan protokol. "\r\n\r\n"pada baris yang sama: dua CRLF berturut-turut menghasilkan baris kosong — pemisah resmi antara header dan body, sama seperti pada anatomi di atas."Content-Length" => strlen($body): panjang body dihitung otomatis denganstrlen(), sehingga nilai28selalu akurat meski isi$bodyberubah.
Membaca Response dari Skrip PHP #
Sejauh ini PHP selalu berperan sebagai penghasil response di sisi server. Namun PHP juga bisa berperan sebagai klien: fungsi file_get_contents() yang biasa membaca berkas dapat membaca URL http:// karena PHP memiliki stream wrapper untuk HTTP. Saat wrapper tersebut dipanggil, PHP otomatis membuat variabel $http_response_header berisi baris-baris header dari response yang diterima.
Skrip berikut memanggil server lokal dari chapter sebelumnya lalu mencetak isi response secara rapi. Jalankan server lebih dulu (php -S 127.0.0.1:8099 pada folder berisi halo.php), lalu jalankan skrip ini di terminal lain:
<?php
$isi = file_get_contents("http://127.0.0.1:8099/halo.php");
foreach ($http_response_header as $baris) {
// Header Date berisi waktu saat response dibuat — selalu berubah,
// jadi dilewati agar hasil mudah dibaca
if (str_starts_with($baris, "Date:")) {
continue;
}
echo $baris . "\n";
}
echo "Body: $isi\n";Hasil berikut dicetak oleh skrip tersebut pada server PHP penulis Chapter ini (baris Date: yang difilter tidak ditampilkan):
HTTP/1.1 200 OK
Host: 127.0.0.1:8099
Connection: close
X-Powered-By: PHP/8.4.23
Content-type: text/html; charset=UTF-8
Body: Halo dari server PHP!Ada tiga hal yang perlu dicermati dari hasil di atas. Pertama, elemen ke-0 $http_response_header adalah baris status (HTTP/1.1 200 OK), sedangkan elemen berikutnya adalah header satu per satu — formatnya siap diolah dengan str_starts_with() atau explode(). Kedua, isi $isi adalah seluruh body response, yaitu hasil echo dari halo.php. Ketiga, header seperti X-Powered-By dan Content-type dikirim otomatis oleh server PHP tanpa Anda menulis satu baris pun. (Satu keunikan kecil: header Host muncul karena built-in server PHP menuliskannya balik ke response — server produksi seperti Nginx umumnya tidak melakukannya.)
Dari echo Menjadi Response #
Bagaimana persisnya kode PHP Anda berubah menjadi response? Jawabannya sederhana: PHP menyusun response secara bertahap selama skrip berjalan. Setiap echo dan print menambahkan byte ke body; fungsi header() menambahkan header; fungsi http_response_code() mengatur baris status. Jika Anda tidak mengatur apa pun, PHP memakai nilai default: status 200 dan Content-Type: text/html; charset=UTF-8 — persis seperti transkrip curl -v pada chapter sebelumnya.
Pemetaan berikut merangkum ketiga alat tersebut:
| Kode PHP | Bagian response yang diisi |
|---|---|
http_response_code(404); | baris status |
header("Location: /login"); | header |
echo "Halo!"; | body |
Satu aturan penting menyertai ketiganya: baris status dan header harus dikirim sebelum byte body pertama keluar. Browser menerima baris status dan header di bagian paling awal pesan, jadi begitu echo pertama dieksekusi, pintu pengaturan header tertutup. Konsekuensi praktis aturan ini — termasuk peringatan headers already sent yang melegendaris — akan kita bahas tuntas pada chapter Headers.
Ringkasan #
Request terdiri atas baris permintaan, header, baris kosong, dan body; response membaliknya dengan baris status di depan. PHP hadir di kedua sisi: sebagai klien lewat file_get_contents() beserta variabel otomatis $http_response_header, dan sebagai penyusun response lewat echo, header(), dan http_response_code(). Satu bagian dari baris permintaan masih sengaja kita tunda: token pertama bernama method. Method inilah yang menentukan maksud sebuah request — membaca, mengirim, mengubah, atau menghapus — dan menjadi fokus chapter berikutnya.
Referensi #
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
contoh.php
Unduh berkas<?php
// contoh.php — rangkuman contoh Chapter "Request dan Response"
// Jalankan dengan: php contoh.php
function buatResponseMentah(string $barisStatus, array $headers, string $body): string
{
$bagian = [$barisStatus];
foreach ($headers as $nama => $nilai) {
$bagian[] = $nama . ": " . $nilai;
}
return implode("\r\n", $bagian) . "\r\n\r\n" . $body;
}
$body = "Halo, Budi!\nSelamat belajar.";
echo "== Anatomi response mentah ==\n";
echo buatResponseMentah(
"HTTP/1.1 200 OK",
[
"Content-Type" => "text/plain; charset=UTF-8",
"Content-Length" => strlen($body),
],
$body,
);
echo "\n-- akhir response --\n";