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.

Response mentah
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.

KelasArtiSiapa yang salah
1xxInformasi. Request masih diproses.Tidak ada. Anda jarang melihatnya secara langsung.
2xxSukses. Server melakukan yang Anda minta.Tidak ada.
3xxPengalihan. Cari di tempat lain.Tidak ada. Klien harus menindaklanjuti.
4xxError klien. Request-nya salah.Klien: input buruk, tanpa izin, URL salah.
5xxError 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

KodeNamaPenggunaan umum
200OKRequest berhasil dan body berisi hasilnya.
201CreatedSebuah POST membuat data baru.
204No ContentBerhasil dan sengaja tidak ada body. Umum setelah DELETE.
301 / 302Moved Permanently / FoundResource ada di URL pada header Location.
304Not ModifiedSalinan di cache Anda masih terbaru. Dibahas bersama caching.
400Bad RequestRequest-nya rusak atau ada nilai yang tidak valid.
401UnauthorizedTanpa kredensial, atau kredensial salah. Meski namanya begitu, artinya belum terautentikasi.
403ForbiddenKredensialnya benar, tetapi pengguna ini tidak boleh melakukannya.
404Not FoundTidak ada apa pun di URL ini, atau tidak ada data dengan ID ini.
405Method Not AllowedURL-nya ada, tetapi tidak dengan method ini.
409ConflictRequest bentrok dengan keadaan saat ini, misalnya email ganda.
422Unprocessable ContentSintaksnya benar tetapi datanya melanggar aturan.
429Too Many RequestsAnda mencapai rate limit. Pelan-pelan.
500Internal Server ErrorError yang tidak tertangani di server.
502Bad GatewayProxy menerima jawaban buruk dari server di belakangnya.
503Service UnavailableServer 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:

GET/api/status/201
GET/api/status/503

Dari curl, 503 terlihat seperti ini:

Response
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:

Response untuk GET /api/status/302
HTTP/1.1 302 Found
Content-Type: application/json; charset=utf-8
location: /api/echo

Browser 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:

GET/api/Products?limit=2&page=3
Header response
HTTP/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: 10

Content-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:

GET/api/formats/no-content
Request ini memakai endpoint untuk anggota yang sudah masuk.MasukBuat akun gratis
Response
HTTP/1.1 204 No Content
x-powered-by: TestingAPIs

Kode 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:

GET/api/formats/wrong-content-type
Request ini memakai endpoint untuk anggota yang sudah masuk.MasukBuat akun gratis
Response
HTTP/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-Type cocok 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": false dan coba minta.

Berlatih dan melangkah lebih jauh