Anatomi Protokol HTTP & Siklus Request-Response
Setiap kali Anda memuat aplikasi web atau aplikasi mobile, sebenarnya terjadi percakapan antara klien (browser, aplikasi mobile) dan server backend. Bahasa percakapan itu adalah HTTP (HyperText Transfer Protocol) — protokol yang mengatur bagaimana permintaan dikirim dan bagaimana jawaban diterima.
Siklus Request-Response Lifecycle
HTTP adalah protokol request-response: setiap percakapan selalu dimulai dari klien. Server tidak pernah menghubungi klien lebih dulu.
Klien (Frontend/Mobile) Server Backend
| |
| 1. HTTP Request (GET /users) |
|-------------------------------------->|
| 2. Proses logika bisnis
| 3. Query ke database
| |
| 4. HTTP Response (200 OK + JSON) |
|<--------------------------------------|
Tahapannya secara berurutan:
- Klien mengirim HTTP Request — misalnya
GET /api/users?role=ADMINdari halaman frontend. - Server memproses logika bisnis — route handler / controller memanggil service, lalu service memutuskan apa yang harus dilakukan.
- Server berinteraksi dengan database — mengambil atau menyimpan data lewat SQL.
- Server mengirim HTTP Response — status code + body (biasanya JSON), kembali ke klien.
Struktur HTTP Message
Baik request maupun response memiliki struktur yang sama: start line, headers, dan (opsional) body.
HTTP Request
POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
User-Agent: Mozilla/5.0 (Mobile)
{"email":"hendro@mail.com","role":"ADMIN"}
| Bagian | Contoh | Fungsi |
|---|---|---|
| Request line | POST /api/users HTTP/1.1 | Method + path + versi protokol |
| Headers | Content-Type, Authorization, User-Agent | Metadata tambahan tentang request |
| Body | {...JSON...} | Data yang dikirim (untuk POST/PUT/PATCH) |
Headers yang paling sering ditemui di backend
| Header | Contoh | Kegunaan |
|---|---|---|
Content-Type | application/json | Format isi body (request & response) |
Authorization | Bearer <token> | Kredensial/identitas klien |
User-Agent | Mozilla/5.0, okhttp/4.9 | Jenis aplikasi klien |
Accept | application/json | Format yang klien mau terima |
Cache-Control | no-store | Aturan caching |
HTTP Response
HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/users/42
{"id":42,"email":"hendro@mail.com","role":"ADMIN"}
| Bagian | Contoh | Fungsi |
|---|---|---|
| Status line | HTTP/1.1 201 Created | Versi + status code + pesan singkat |
| Headers | Content-Type, Location | Metadata tentang response |
| Body | {...JSON...} | Data hasil proses |
HTTP Methods: Memilih Kata Kerja yang Tepat
HTTP Methods adalah "kata kerja" yang menyatakan maksud request. Memilih method yang tepat membuat API Anda konsisten dan mudah diprediksi.
| Method | Fungsi | Idempoten* | Body? | Contoh Backend |
|---|---|---|---|---|
GET | Ambil data | Ya | Tidak | GET /api/users — list user |
POST | Buat data baru | Tidak | Ya | POST /api/users — daftarkan user |
PUT | Ganti data seutuhnya | Ya | Ya | PUT /api/users/42 — overwrite seluruh field |
PATCH | Update sebagian field | Tidak | Ya | PATCH /api/users/42 — ganti role saja |
DELETE | Hapus data | Ya | Tidak | DELETE /api/users/42 — hapus user |
* Idempoten = memanggil berulang kali memberi hasil akhir yang sama. GET berkali-kali tidak mengubah apa pun; POST berkali-kali bisa membuat banyak data.
// Contoh mapping di Spring Boot
@GetMapping("/api/users") List<User> listUsers()
@PostMapping("/api/users") User createUser(@RequestBody User user)
@PutMapping("/api/users/{id}") User replaceUser(@PathVariable Long id, @RequestBody User user)
@PatchMapping("/api/users/{id}") User patchUser(@PathVariable Long id, @RequestBody Map<String,Object> patch)
@DeleteMapping("/api/users/{id}") void deleteUser(@PathVariable Long id)
Kesalahan umum: memakai POST untuk ambil data atau GET untuk aksi yang mengubah data (misal GET /api/delete-user). Gunakan method sesuai maknanya — ini bagian dari disiplin desain API yang baik.
Klasifikasi HTTP Status Codes
Status codes adalah "nilai rapor" dari setiap response. Backend engineer wajib mengenali kelompoknya.
2xx — Success (permintaan berhasil)
| Code | Nama | Kapan dipakai |
|---|---|---|
200 | OK | GET berhasil, data dikembalikan |
201 | Created | POST berhasil, data baru tersimpan di database |
204 | No Content | Sukses tapi tidak ada isi yang perlu dikirim (biasanya DELETE) |
4xx — Client Error (kesalahan ada di sisi pengirim)
| Code | Nama | Kapan dipakai |
|---|---|---|
400 | Bad Request | Validasi gagal, body tidak sesuai format |
401 | Unauthorized | Belum login / token salah / token kedaluwarsa |
403 | Forbidden | Sudah login tapi tidak punya hak akses ke resource |
404 | Not Found | Endpoint atau resource tidak ada |
409 | Conflict | Bentrok dengan state saat ini (misal email sudah terdaftar) |
422 | Unprocessable Entity | Body valid secara format, tapi gagal di level bisnis |
Perbedaan kunci 401 vs 403: 401 = "saya tidak tahu siapa Anda" (identitas tidak valid). 403 = "saya tahu siapa Anda, tapi Anda tidak diizinkan masuk ke sini" (otorisasi gagal).
5xx — Server Error (kesalahan di sisi server)
| Code | Nama | Kapan dipakai |
|---|---|---|
500 | Internal Server Error | Ada error di kodingan backend, atau koneksi database terputus |
502 | Bad Gateway | Server penerima mendapat jawaban tidak valid dari upstream |
503 | Service Unavailable | Server sedang kelebihan beban / sedang maintenance |
// Contoh pola: lempar exception, biarkan handler memetakan ke status code
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(NotFoundException.class)
public ResponseEntity<ApiError> handleNotFound(NotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ApiError("RESOURCE_NOT_FOUND", ex.getMessage()));
}
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<ApiError> handleBadRequest(IllegalArgumentException ex) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(new ApiError("VALIDATION_FAILED", ex.getMessage()));
}
}
Ringkasan
HTTP adalah bahasa percakapan klien-server: klien selalu memulai dengan request, server merespons dengan response. Gunakan method yang tepat untuk menyatakan maksud, isi headers dengan metadata yang benar, dan jawab selalu dengan status code yang akurat agar klien (dan developer lain) bisa mengambil keputusan tanpa menebak-nebak. Selalu buat response error konsisten dengan code mesin yang bisa diprogram, bukan sekadar teks.
Lanjut ke Dasar Database Relasional & SQL untuk memahami bagaimana data disimpan secara permanen.