Koneksi database sudah jalan, proyek sudah rapi — sekarang saatnya bikin endpoint pertama yang beneran berguna! Di part ini kita akan belajar bagaimana cara “membaca” data dari database dan mengirimkannya ke pengguna lewat HTTP. Ini adalah fondasi dari semua aplikasi web modern!
Apa Itu Endpoint GET?
Sebelum nulis kode, pahami dulu konsepnya. Dalam REST API, method HTTP GET dipakai untuk mengambil data — tidak mengubah, tidak menghapus, cuma baca.
Kita akan membuat dua endpoint GET:
| Endpoint | Fungsi |
|---|---|
GET /api/siswa | Ambil semua data siswa |
GET /api/siswa/:id | Ambil detail satu siswa |
Mudah kan? Yuk mulai!
Tambah Data Dummy Dulu
Supaya kita bisa langsung tes hasilnya, masukkan dulu beberapa data dummy ke database. Buka psql atau DBeaver, lalu jalankan query ini:
INSERT INTO siswa (nama, nis, kelas, jurusan, email) VALUES
('Budi Santoso', '2024001', 'XII RPL 1', 'Rekayasa Perangkat Lunak', '[email protected]'),
('Siti Rahayu', '2024002', 'XII RPL 1', 'Rekayasa Perangkat Lunak', '[email protected]'),
('Ahmad Fauzi', '2024003', 'XI TKJ 2', 'Teknik Komputer Jaringan', '[email protected]'),
('Dewi Lestari', '2024004', 'X MM 1', 'Multimedia', '[email protected]');
Sekarang ada 4 siswa di database kita. Siap untuk diambil!
Membuat Endpoint GET Semua Siswa
Buka file src/routes/siswa.ts dan ganti semua isinya dengan kode berikut:
import { Hono } from 'hono'
import sql from '../db'
const siswa = new Hono()
// GET /api/siswa — Ambil semua data siswa
siswa.get('/', async (c) => {
const semuaSiswa = await sql`
SELECT id, nama, nis, kelas, jurusan, email, created_at
FROM siswa
ORDER BY created_at DESC
`
return c.json({
success: true,
total: semuaSiswa.length,
data: semuaSiswa
})
})
export default siswa
Jalankan server dengan bun run dev, lalu buka http://localhost:3000/api/siswa.
Kamu akan mendapat respons JSON seperti ini:
{
"success": true,
"total": 4,
"data": [
{
"id": 1,
"nama": "Budi Santoso",
"nis": "2024001",
"kelas": "XII RPL 1",
"jurusan": "Rekayasa Perangkat Lunak",
"email": "[email protected]",
"created_at": "2025-05-19T..."
},
...
]
}
Yeay! Data siswa berhasil tampil! 🎉
Membuat Endpoint GET Satu Siswa
Sekarang kita tambah endpoint untuk mengambil detail satu siswa berdasarkan ID-nya. Tambahkan kode ini di bawah endpoint GET semua siswa:
// GET /api/siswa/:id — Ambil satu siswa berdasarkan ID
siswa.get('/:id', async (c) => {
const id = Number(c.req.param('id'))
// Validasi: pastikan ID adalah angka yang valid
if (isNaN(id) || id <= 0) {
return c.json({
success: false,
message: 'ID tidak valid. Harus berupa angka positif.'
}, 400)
}
const result = await sql`
SELECT id, nama, nis, kelas, jurusan, email, created_at
FROM siswa
WHERE id = ${id}
`
// Kalau data tidak ditemukan
if (result.length === 0) {
return c.json({
success: false,
message: `Siswa dengan ID ${id} tidak ditemukan.`
}, 404)
}
return c.json({
success: true,
data: result[0]
})
})
Coba akses http://localhost:3000/api/siswa/1 — kamu akan melihat detail Budi Santoso.
Sekarang coba akses http://localhost:3000/api/siswa/999 — yang ini akan mengembalikan pesan error 404 karena ID 999 tidak ada di database.
Fitur Tambahan: Filter dan Pencarian
Aplikasi yang lebih berguna biasanya punya fitur pencarian. Yuk kita tambahkan fitur cari siswa berdasarkan nama atau kelas! Update endpoint GET semua siswa menjadi seperti ini:
// GET /api/siswa — Ambil semua siswa, dengan opsional filter
siswa.get('/', async (c) => {
const cariNama = c.req.query('nama')
const cariKelas = c.req.query('kelas')
let semuaSiswa
if (cariNama) {
// Filter berdasarkan nama (tidak case-sensitive)
semuaSiswa = await sql`
SELECT id, nama, nis, kelas, jurusan, email, created_at
FROM siswa
WHERE LOWER(nama) LIKE ${'%' + cariNama.toLowerCase() + '%'}
ORDER BY nama ASC
`
} else if (cariKelas) {
// Filter berdasarkan kelas
semuaSiswa = await sql`
SELECT id, nama, nis, kelas, jurusan, email, created_at
FROM siswa
WHERE LOWER(kelas) LIKE ${'%' + cariKelas.toLowerCase() + '%'}
ORDER BY nama ASC
`
} else {
// Tanpa filter, tampilkan semua
semuaSiswa = await sql`
SELECT id, nama, nis, kelas, jurusan, email, created_at
FROM siswa
ORDER BY created_at DESC
`
}
return c.json({
success: true,
total: semuaSiswa.length,
data: semuaSiswa
})
})
Sekarang kamu bisa pakai fitur pencarian seperti ini:
GET /api/siswa?nama=budi— cari siswa bernama “budi”GET /api/siswa?kelas=RPL— cari siswa di kelas yang mengandung kata “RPL”GET /api/siswa— tampilkan semua siswa
Testing dengan Curl
Sambil menunggu kita buat frontend, kita bisa tes API langsung dari terminal menggunakan curl. Buka terminal baru dan coba perintah ini:
# Ambil semua siswa
curl http://localhost:3000/api/siswa
# Ambil siswa ID 1
curl http://localhost:3000/api/siswa/1
# Cari siswa bernama "budi"
curl "http://localhost:3000/api/siswa?nama=budi"
# Coba ID yang tidak ada
curl http://localhost:3000/api/siswa/999
Kalau kamu lebih suka tools dengan tampilan yang lebih enak, coba install Bruno atau Postman — mereka gratis dan sangat membantu untuk testing REST API.
Konsep Penting: Status Code HTTP
Di kode di atas, kita menggunakan angka-angka seperti 400 dan 404. Ini namanya HTTP Status Code — kode standar yang memberitahu klien (browser, aplikasi lain) tentang hasil dari request mereka:
| Kode | Arti | Kapan Dipakai |
|---|---|---|
200 | OK | Request berhasil (default di Hono) |
400 | Bad Request | Input dari klien tidak valid |
404 | Not Found | Data yang dicari tidak ada |
500 | Internal Server Error | Ada error di sisi server |
Menggunakan status code yang tepat itu penting banget — ini membuat API kamu lebih profesional dan mudah dipakai oleh siapapun!
File Lengkap src/routes/siswa.ts Sejauh Ini
Ini tampilan lengkap file kamu setelah part ini:
import { Hono } from 'hono'
import sql from '../db'
const siswa = new Hono()
siswa.get('/', async (c) => {
const cariNama = c.req.query('nama')
const cariKelas = c.req.query('kelas')
let semuaSiswa
if (cariNama) {
semuaSiswa = await sql`
SELECT id, nama, nis, kelas, jurusan, email, created_at FROM siswa
WHERE LOWER(nama) LIKE ${'%' + cariNama.toLowerCase() + '%'}
ORDER BY nama ASC
`
} else if (cariKelas) {
semuaSiswa = await sql`
SELECT id, nama, nis, kelas, jurusan, email, created_at FROM siswa
WHERE LOWER(kelas) LIKE ${'%' + cariKelas.toLowerCase() + '%'}
ORDER BY nama ASC
`
} else {
semuaSiswa = await sql`
SELECT id, nama, nis, kelas, jurusan, email, created_at
FROM siswa ORDER BY created_at DESC
`
}
return c.json({ success: true, total: semuaSiswa.length, data: semuaSiswa })
})
siswa.get('/:id', async (c) => {
const id = Number(c.req.param('id'))
if (isNaN(id) || id <= 0) {
return c.json({ success: false, message: 'ID tidak valid.' }, 400)
}
const result = await sql`
SELECT id, nama, nis, kelas, jurusan, email, created_at
FROM siswa WHERE id = ${id}
`
if (result.length === 0) {
return c.json({ success: false, message: `Siswa dengan ID ${id} tidak ditemukan.` }, 404)
}
return c.json({ success: true, data: result[0] })
})
export default siswa
Recap dan Langkah Selanjutnya
Di part ini kita sudah berhasil membuat:
- Endpoint
GET /api/siswadengan fitur pencarian by nama dan kelas - Endpoint
GET /api/siswa/:iddengan penanganan error 404 - Pemahaman tentang HTTP Status Code
Di Part #4, giliran kita buat endpoint POST untuk menambah data siswa baru ke database. Kita juga mulai menyentuh sedikit validasi input supaya data yang masuk tidak sembarangan!
Coba dulu semua endpoint-nya, dan tulis di komentar kalau ada yang error ya! 💪
Tinggalkan Balasan