Buat package pagination untuk mengekstrak parameter dari URL dan membuat meta response:
19.4 DTO untuk Pagination
19.5 Model Pagination
19.6 Repository dengan Pagination
Update repository untuk mendukung search, order, sort, limit, dan offset:
19.7 Service dengan Pagination
19.8 Handler dengan Pagination
19.9 Contoh Request dan Response
Response:
Request Tanpa Parameter (Menggunakan Default)
page=1
limit=10
order=name
sort=asc
19.10 Keamanan: Mencegah SQL Injection
Perhatikan penggunaan whitelist mapping untuk field order:
Ini mencegah attacker menyisipkan SQL injection melalui parameter order.
19.11 Catatan: Kapan Pagination Tidak Diperlukan
Untuk resource dengan jumlah data sedikit (misal: roles, config), pagination tidak diperlukan. Juga untuk list access yang mengembalikan semua data dalam format tree, pagination tidak diperlukan.
Ringkasan Bab 19
Di bab ini kita telah belajar:
Komponen
File
Fungsi
Response Enhancement
pkg/response/response.go
Tambahan field Meta
Pagination Helper
pkg/pagination/pagination.go
Extract URL params & build meta
Pagination DTO
internal/dto/pagination_response.go
MetaResponse, PaginationResponse
Pagination Model
internal/model/pagination.go
Struct untuk internal
Repository
user_repository.go
COUNT query + LIMIT/OFFSET
Service
users.go
Hitung offset, return pagination
Handler
user_handler.go
Extract params, response dengan meta
Parameter yang Didukung:
Parameter
Default
Contoh
page
1
page=3
limit
10
limit=25
order
name
order=email
sort
asc
sort=desc
search
(none)
search=joh
Manfaat yang kita peroleh:
✅ Response lebih ringan (hanya data yang dibutuhkan)
✅ Client bisa menampilkan navigasi halaman
✅ Sorting dan pencarian terintegrasi
✅ Proteksi SQL injection dengan whitelist field
✅ Konsistensi response dengan field meta
Yang akan datang:
Saat ini validasi masih sederhana
Bab selanjutnya: Unit Testing – menguji kode secara otomatis
orderByMap := map[string]string{
"id": "id",
"name": "LOWER(name)",
"username": "LOWER(username)",
"email": "LOWER(email)",
"is_active": "is_active",
"created_at": "created_at",
}
order, ok := orderByMap[order]
if !ok {
order = "id" // default jika tidak ada di whitelist
}