Membaca response
Kode status, header response, dan body.
Setiap request mendapat tepat satu response (kecuali koneksinya putus, yang merupakan jenis jawaban tersendiri dan dibahas di pelajaran berikutnya). Response punya tiga bagian: baris status, header, dan body. Penguji pemula cenderung hanya melihat body, karena di sanalah datanya. Sebagian besar bug yang lolos justru ada di dua bagian lainnya.
Seperti apa sebuah response
Seperti request, response HTTP/1.1 adalah teks biasa. Ini response untuk GET /api/health, seperti yang ditampilkan curl dengan opsi -i (yang mencetak header bersama body). Beberapa header infrastruktur dihapus.
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
x-powered-by: TestingAPIs
{"status":"healthy","uptimeSeconds":3542,"timestamp":"2026-09-30T18:28:12Z"}Baris pertama adalah baris status: versi protokol, kode status tiga digit, dan frasa alasan singkat. Lalu datang header, satu per baris, kemudian baris kosong, lalu body. Frasa alasan hanya untuk manusia. Klien dan tes sebaiknya melihat angkanya. HTTP/2 menghapus frasa alasan sepenuhnya, jadi tes yang memeriksa teks "OK" bisa rusak saat server diperbarui.
Kelas kode status
Digit pertama kode status memberi tahu kelas response. Sering kali Anda bisa menilai hasil hanya dari digit itu.
| Kelas | Arti | Siapa yang salah |
|---|---|---|
| 1xx | Informasi. Request masih diproses. | Tidak ada. Anda jarang melihatnya secara langsung. |
| 2xx | Sukses. Server melakukan yang Anda minta. | Tidak ada. |
| 3xx | Pengalihan. Cari di tempat lain. | Tidak ada. Klien harus menindaklanjuti. |
| 4xx | Error klien. Request-nya salah. | Klien: input buruk, tanpa izin, URL salah. |
| 5xx | Error server. Request-nya mungkin baik-baik saja. | Server atau sesuatu di belakangnya. |
Kolom terakhir itulah alasan kode status sangat penting dalam pengujian. 4xx berarti "perbaiki request Anda". 5xx berarti "ada yang rusak di pihak kami". Jika Anda mengirim sampah dan mendapat 500, itu bug meskipun request-nya buruk, karena server crash padahal seharusnya menolak input itu dengan sopan memakai 400. Menemukan 500 semacam itu adalah salah satu hal paling produktif yang bisa dilakukan penguji pemula.
Kode yang paling sering Anda lihat
| Kode | Nama | Penggunaan umum |
|---|---|---|
| 200 | OK | Request berhasil dan body berisi hasilnya. |
| 201 | Created | Sebuah POST membuat data baru. |
| 204 | No Content | Berhasil dan sengaja tidak ada body. Umum setelah DELETE. |
| 301 / 302 | Moved Permanently / Found | Resource ada di URL pada header Location. |
| 304 | Not Modified | Salinan di cache Anda masih terbaru. Dibahas bersama caching. |
| 400 | Bad Request | Request-nya rusak atau ada nilai yang tidak valid. |
| 401 | Unauthorized | Tanpa kredensial, atau kredensial salah. Meski namanya begitu, artinya belum terautentikasi. |
| 403 | Forbidden | Kredensialnya benar, tetapi pengguna ini tidak boleh melakukannya. |
| 404 | Not Found | Tidak ada apa pun di URL ini, atau tidak ada data dengan ID ini. |
| 405 | Method Not Allowed | URL-nya ada, tetapi tidak dengan method ini. |
| 409 | Conflict | Request bentrok dengan keadaan saat ini, misalnya email ganda. |
| 422 | Unprocessable Content | Sintaksnya benar tetapi datanya melanggar aturan. |
| 429 | Too Many Requests | Anda mencapai rate limit. Pelan-pelan. |
| 500 | Internal Server Error | Error yang tidak tertangani di server. |
| 502 | Bad Gateway | Proxy menerima jawaban buruk dari server di belakangnya. |
| 503 | Service Unavailable | Server kelebihan beban atau sedang dalam pemeliharaan. |
API tidak selalu sepakat soal beberapa kode ini. Satu tim mengembalikan 400 untuk setiap error validasi dan tim lain memakai 422. Ada yang mengembalikan 200 untuk penghapusan dengan pesan di body, ada yang 204 tanpa apa-apa. Keduanya tidak salah. Yang Anda periksa adalah apakah API sesuai dengan dokumentasinya sendiri dan konsisten dari satu endpoint ke endpoint lain.
Mencoba kode status
/api/status/{code} menjawab dengan kode apa pun yang Anda taruh di path. Ini berguna untuk melihat bagaimana sebuah alat atau library klien berperilaku saat menerima status tertentu. Coba beberapa:
/api/status/201/api/status/503Dari curl, 503 terlihat seperti ini:
HTTP/1.1 503 Service Unavailable
Content-Type: application/json; charset=utf-8
retry-after: 5
{
"status": 503,
"statusText": "Service Unavailable",
"category": "server-error",
"message": "This is a 503 response. Use /api/status/{code} to request any status."
}Perhatikan header retry-after: 5. 503 atau 429 sering memberi tahu klien berapa detik harus menunggu sebelum mencoba lagi, dan klien yang baik mematuhinya. Anda memeriksa bahwa header itu ada, bukan hanya statusnya.
Kode di luar rentang yang valid ditolak. /api/status/999 kembali sebagai 400 dengan pesan Status code must be between 200 and 599 (1xx cannot be sent as a final response). Dan /api/status/abc mengembalikan 404 dengan body kosong, karena abc sama sekali tidak cocok dengan route-nya. Dua input buruk, dua jenis kegagalan yang berbeda. Anda akan sering melihat pola ini: nilai dengan tipe yang salah cenderung gagal di lapisan routing, sebelum kode aplikasi sempat berjalan.
Pengalihan
Response 3xx biasanya tidak punya body yang berguna. Bagian pentingnya adalah header Location, yang menyebut ke mana harus pergi berikutnya:
HTTP/1.1 302 Found
Content-Type: application/json; charset=utf-8
location: /api/echoBrowser dan sebagian besar library HTTP mengikuti pengalihan secara otomatis dan hanya menampilkan response terakhir. Itu praktis sampai Anda perlu menguji pengalihannya sendiri. curl tidak mengikutinya kecuali Anda menambahkan -L, sehingga ia alat yang lebih baik untuk ini.
Header response
Header response mendeskripsikan body dan memberi instruksi kepada klien. Minta halaman 3 dari daftar produk, dua produk per halaman:
/api/Products?limit=2&page=3HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
x-page: 3
x-per-page: 2
x-total-count: 20
x-total-pages: 10Content-Type menyatakan body-nya JSON dalam UTF-8. Empat header x-page dan x-total membawa detail paginasi: ada 20 produk, 10 halaman, dan ini halaman 3. Body-nya hanya array berisi dua produk, jadi klien yang mengabaikan header ini tidak punya cara untuk tahu bahwa masih ada lagi. Header yang diawali X- adalah header kustom buatan API. Yang mendokumentasikannya adalah API, bukan standar HTTP.
Beberapa header menyimpan waktu sebagai Unix timestamp: jumlah detik sejak 1 Januari 1970, UTC. API dengan rate limit sering mengirim satu di x-ratelimit-reset untuk memberi tahu kapan jatah Anda diatur ulang. Konversikan dulu sebelum memercayainya: waktu reset di masa lalu, atau bertahun-tahun lagi, adalah bug yang hanya tertangkap jika Anda membaca header alih-alih melewatinya. (Konverter timestamp melakukan konversinya.)
Anda mungkin mengharapkan header Content-Length. API ini kebanyakan mengirim Transfer-Encoding: chunked sebagai gantinya, yang berarti body dikirim dalam potongan-potongan dan ukuran totalnya tidak diumumkan di awal. Keduanya valid. Sebuah response punya salah satunya, bukan keduanya.
Body
Body adalah datanya: sebuah produk, sebuah daftar, pesan error, gambar. Content-Type menyebut cara membacanya. Sebagian besar pemeriksaan Anda akan dilakukan pada body, dan Membaca JSON membahasnya secara rinci. Ada dua kasus khusus lebih dulu.
Tanpa body sama sekali
204 berarti sukses tanpa body, dengan sengaja. Response-nya juga tidak punya Content-Type, karena tidak ada yang perlu dideskripsikan:
/api/formats/no-contentHTTP/1.1 204 No Content
x-powered-by: TestingAPIsKode klien yang selalu memanggil response.json() akan crash di sini, karena string kosong bukan JSON yang valid. Jika Anda menulis helper tes yang mem-parse setiap response, helper itu harus bisa menangani body kosong.
Saat header berbohong
Status, header, dan body dihasilkan oleh bagian server yang berbeda, dan tidak ada yang memaksa mereka untuk cocok. Ini sebuah response yang mengaku sebagai HTML:
/api/formats/wrong-content-typeHTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
{"id":1,"name":"Alice Johnson","email":"alice@example.com","roles":["admin","editor"],"active":true,"score":98.5,"manager":null}Body-nya JSON yang sepenuhnya baik. Orang yang membacanya tidak akan pernah melihat masalah. Browser akan mencoba menampilkannya sebagai halaman web, dan beberapa library HTTP akan menolak mem-parse-nya sebagai JSON atau mengembalikannya sebagai string. Endpoint ini sengaja dibuat rusak. Di sistem sungguhan, bug yang sama biasanya berasal dari halaman error yang dibuat proxy atau pengaturan bawaan framework. Tes Anda sebaiknya memeriksa Content-Type secara eksplisit.
Kebalikannya juga terjadi: status 200 dengan body yang berbunyi {"success": false}. Beberapa API melaporkan setiap error dengan cara itu. Alat pemantauan yang menghitung response 5xx tidak pernah melihat kegagalan itu, begitu juga tes yang hanya memeriksa kode status. Jika sebuah API melakukan ini, tes Anda harus membaca body di setiap response.
Yang diperiksa di setiap response
Sebelum melihat satu field data pun, pastikan hal-hal dasarnya. Ini hanya butuh beberapa detik dan menangkap jumlah bug yang mengejutkan.
- Kode status sesuai dengan yang dijanjikan dokumentasi untuk situasi ini.
Content-Typecocok dengan body yang benar-benar Anda terima.- Header yang disebut dokumentasi (paginasi,
Location,Retry-After) ada dan masuk akal. - Body bisa di-parse dan bentuknya sesuai harapan Anda.
- Response error mengikuti format yang sama dengan error lain dari API ini.
Latihan
Untuk setiap request, catat kode status, Content-Type, dan satu kalimat tentang body-nya.
/api/status/418. Cari tahu mengapa kode ini ada./api/formats/emptymasuk untuk melihat. Apa bedanya dengan/api/formats/no-contentmasuk untuk melihat? Satu mengembalikan 200 dan satunya 204. Menurut Anda mana yang lebih mudah ditangani klien?/api/Products?limit=2&page=99. Tidak ada halaman 99. Status dan body apa yang Anda dapat, dan apa kata header paginasinya? Apakah Anda akan merancangnya dengan cara yang sama?/api/status/list. Cari kode di daftar itu yang bertanda"supported": falsedan coba minta.