Route Handler
Endpoint HTTP dengan alamat tetap, cocok untuk membaca data daftar tabel dan untuk klien yang memanggil lewat parameter URL.
Membaca sekitar 1 menit
Endpoint HTTP dengan alamat tetap, cocok untuk membaca data daftar tabel dan untuk klien yang memanggil lewat parameter URL.
Dipakai untuk pencarian dan paginasi user, role, feature, item, audit log, serta percobaan login lewat GET. Bila belum login atau tidak berhak, ia membalas 401 atau 403 berupa JSON.
Aturan siapa boleh membaca modul mana ditulis sekali di penjaga izin, lalu dipakai bersama oleh halaman dan endpoint ini.
Kapan memakai Route Handler, bukan Server Action
Kalau Server Action sangat pas untuk mengubah data (mutasi), membaca daftar data tabel yang punya pencarian, halaman bertahap (paginasi), dan penyimpanan cache di browser justru lebih bersih lewat endpoint HTTP GET biasa. Di sinilah Route Handler dipakai.
Satu pola untuk semua endpoint daftar
Semua endpoint daftar (/api/users, /api/roles, /api/features, /api/audit-logs, /api/login-attempts) mengikuti struktur yang identik: periksa hak baca, validasi parameter query URL, panggil query database, lalu kembalikan JSON dengan header privat.
export async function GET(request: NextRequest) {
try {
await requirePermission("user", "read");
const params = listParamsSchema.parse(
Object.fromEntries(request.nextUrl.searchParams)
);
const data = await getUsers(params); // kolom password sudah dibuang di select
return NextResponse.json(
{ ...data, page: params.page, limit: params.limit },
{ headers: PRIVATE_HEADERS }
);
} catch (e) {
return apiError(e);
}
}Aturan siapa boleh membaca data apa cukup ditulis satu kali, lalu dipakai bersama oleh halaman server dan endpoint API.
Kenapa tidak dialihkan ke halaman login
Saat komponen tabel di browser meminta data ke /api/users dan sesi pengguna kebetulan habis, komponen tidak mengharapkan balasan HTML halaman login, melainkan status HTTP 401 atau 403 berbentuk JSON. Fungsi apiError menerjemahkan UnauthorizedError menjadi status 401 dan ForbiddenError menjadi status 403 secara konsisten.
Jebakan yang saya temui
- Tidak sengaja mengikutsertakan kolom sensitif seperti hash password atau secret MFA saat melakukan query daftar user. Solusinya adalah selalu memakai select eksplisit di lapisan query.
- Lupa memasang Cache-Control: no-store pada header respons API, yang bisa membuat data tabel sensitif tersimpan di cache bersama.
- Membiarkan parameter limit diisi angka ribuan oleh pengguna iseng. Skema listParamsSchema membatasi nilai limit maksimum agar database tetap ringan.
Ringkasnya
Route Handler menjadi pasangan alami bagi TanStack Query di sisi browser: alamatnya jelas, parameternya tervalidasi lewat URL, dan penjaga keamanannya berbagi fungsi yang sama dengan Server Action.