Tutorial Membuat Middleware Validasi Request API Menggunakan Joi dan Lodash di Node.js

Tutorial Membuat Middleware Validasi Request API Menggunakan Joi dan Lodash di Node.js

id9 min read • 492 views

Tutorial Membuat Middleware Validasi Request API Menggunakan Joi dan Lodash di Node.js

Tutorial Membuat Middleware Validasi Request API Menggunakan Joi dan Lodash di Node.js

Dalam pengembangan backend berbasis Node.js, salah satu tantangan terbesar adalah memastikan data yang masuk ke server benar, aman, dan sesuai struktur yang kita harapkan. Tanpa validasi yang baik, API akan rentan error, bug sulit dilacak, bahkan celah keamanan. Pada tutorial ini, saya akan membahas secara detail cara membuat middleware validasi request menggunakan Joi dan Lodash, berdasarkan potongan kode yang sering saya pakai di proyek API skala menengah.

Middleware ini dirancang fleksibel, reusable, dan bisa digunakan di banyak endpoint tanpa harus menulis validasi berulang-ulang.

Konsep Dasar: Mengapa Validasi Request Itu Wajib?

Setiap request API membawa data dari luar sistem. Artinya, data tersebut tidak bisa dipercaya begitu saja. Bisa saja:

  • Field wajib tidak dikirim
  • Tipe data salah
  • Ada field tambahan yang tidak diinginkan
  • Struktur JSON tidak sesuai kontrak API

Validasi request bertugas sebagai gerbang pertama sebelum data diproses lebih jauh oleh controller dan logic bisnis. Jika data sudah valid sejak awal, maka error di layer berikutnya bisa ditekan drastis.

Baca Juga

 

Gambaran Umum Cara Kerja Middleware Ini

Middleware yang kita buat memiliki alur sebagai berikut:

  1. Mengecek HTTP method (hanya POST dan PUT)
  2. Mengambil path route yang sedang diakses
  3. Mencocokkan route dengan schema Joi yang sesuai
  4. Memvalidasi body
  5. Jika gagal → kirim response error (422)
  6. Jika berhasil → bodydiganti data bersih hasil validasi

Dengan pola ini, controller tidak perlu lagi melakukan pengecekan data secara manual.

 

Import Dependency yang Digunakan

  • const _ = require('lodash');
  • const Joi = require('joi');
  • const Schemas = require('../schemas');

Penjelasan singkat:

  • Lodash (_): membantu manipulasi object dan pengecekan data dengan aman
  • Joi: library validasi schema yang sangat powerful
  • Schemas: kumpulan schema Joi berdasarkan route API

Biasanya Schemas berbentuk object seperti ini:

{
  '/users': userSchema,
  '/login': loginSchema
}

 

Parameter Konfigurasi: useJoiError

  • module.exports = (useJoiError = false) => {

Middleware ini dibuat fleksibel dengan satu parameter opsional:

  • false→ error response sederhana (untuk production)
  • true→ error detail dari Joi (untuk development/debug)

Ini penting agar:

  • Developer mendapat error detail saat development
  • User production tidak melihat pesan teknis yang sensitif

Validasi Parameter Boolean dengan Lodash

  • const _useJoiError = _.isBoolean(useJoiError) && useJoiError;

Di sini kita memastikan bahwa parameter benar-benar boolean. Ini mencegah bug jika middleware dipanggil dengan nilai tidak valid.

 

Membatasi HTTP Method yang Diverifikasi

  • const _supportedMethods = ['post', 'put'];

Kenapa hanya POST dan PUT?

  • GET umumnya tidak punya body
  • DELETE jarang butuh body
  • POST dan PUT paling sering menerima data kompleks

Dengan pembatasan ini, middleware tidak membebani request lain yang tidak perlu divalidasi.

 

Opsi Validasi Joi yang Digunakan

const _validationOptions = {
  abortEarly: false,
  allowUnknown: true,
  stripUnknown: true
};

Penjelasan detail:

  • abortEarly: false
    Semua error dikumpulkan sekaligus, bukan berhenti di error pertama
  • allowUnknown: true
    Field asing boleh masuk sementara
  • stripUnknown: true
    Field asing otomatis dibuang dari hasil akhir

Kombinasi ini membuat API:

  • Lebih informatif
  • Lebih aman
  • Lebih bersih

 

Struktur Middleware Express

  • return (req, res, next) => {

Middleware menerima tiga parameter utama:

  • req→ data request
  • res→ response handler
  • next→ melanjutkan ke middleware berikutnya

Mengambil Informasi Route dan Method

  • const route = req.route.path;
  • const method = req.method.toLowerCase();

Kenapa pakai req.route.path?

  • Agar schema bisa dipetakan langsung berdasarkan route
  • Lebih rapi daripada hardcode di tiap endpoint

Mengecek Apakah Route Memiliki Schema

  • if (_.includes(_supportedMethods, method) && _.has(Schemas, route)) {

Validasi hanya dijalankan jika:

  1. Method didukung
  2. Schema untuk route tersebut tersedia

Jika salah satu tidak terpenuhi, middleware langsung next() tanpa gangguan.

Mengambil Schema yang Sesuai

  • const _schema = _.get(Schemas, route);

Menggunakan Lodash get lebih aman dibanding akses langsung, karena:

  • Tidak error jika property tidak ada
  • Lebih readable

 

Proses Validasi dengan Joi

  • Joi.validate(req.body, _schema, _validationOptions, (err, data) => {

Di sini terjadi proses inti:

  • body→ data mentah
  • _schema→ aturan validasi
  • _validationOptions→ aturan tambahan
  • data→ hasil validasi yang sudah bersih

 

Struktur Error Detail dari Joi

Jika validasi gagal:

const JoiError = {
  status: 'failed',
  error: {
    original: err._object,
    details: _.map(err.details, ({message, type}) => ({
      message: message.replace(/['"]/g, ''),
      type
    }))
  }
};

Yang dilakukan di sini:

  • Menyimpan data original
  • Mengambil hanya messagedan type
  • Membersihkan tanda kutip agar lebih enak dibaca

Ini sangat membantu frontend developer saat debugging.

Custom Error untuk Production

const CustomError = {
  status: 'failed',
  error: 'Invalid request data. Please review request and try again.'
};

Error ini sengaja dibuat generik agar:

  • Tidak membocorkan struktur internal
  • Aman untuk production
  • Tetap informatif

Mengirim Response Error

  • res.status(422).json(_useJoiError ? JoiError : CustomError);

HTTP status 422 Unprocessable Entity dipilih karena:

  • Request diterima
  • Format benar
  • Tapi isi tidak bisa diproses

 

Pemilihan error berdasarkan konfigurasi useJoiError.

Mengganti req.body dengan Data Bersih

req.body = data;
next();

Ini bagian yang sering dianggap sepele tapi sangat penting.

Artinya:

  • Controller menerima data yang sudah tervalidasi
  • Tidak perlu sanitasi ulang
  • Mengurangi bug logika

Middleware Tetap Aman untuk Route Lain

  • next();

Jika tidak memenuhi syarat validasi, middleware tidak memblokir request lain. Ini membuatnya aman dipasang global.

 

Contoh Penggunaan di Express

Setelah middleware validasi dibuat, penerapannya di aplikasi Express.js sangat sederhana dan rapi. Middleware ini diletakkan di antara route dan controller, sehingga setiap request akan divalidasi terlebih dahulu sebelum logic bisnis dijalankan. Dengan pola ini, controller hanya menerima data yang sudah “bersih” dan sesuai skema.

Contoh penggunaan dasar:

  • const validate = require('./middlewares/validate');
  • app.post('/users', validate(true), userController.create);

Pada contoh di atas, validate(true) berarti middleware akan mengembalikan error detail dari Joi jika validasi gagal. Mode ini sangat cocok digunakan saat tahap development atau debugging, karena developer bisa langsung melihat field mana yang salah, tipe error-nya apa, dan kenapa request ditolak. Ini sangat membantu mempercepat proses pengembangan dan testing API.

Sementara itu, untuk lingkungan production, penggunaan yang disarankan adalah:

  • app.post('/users', validate(), userController.create);

Tanpa parameter true, middleware akan mengirim custom error message yang lebih aman dan user-friendly. Cara ini penting untuk mencegah bocornya detail struktur backend ke client atau pihak luar. Pengguna hanya tahu bahwa data yang dikirim tidak valid, tanpa melihat detail teknis internal.

Keunggulan pola ini adalah konsistensi. Setiap endpoint cukup memanggil validate() tanpa menulis ulang logic pengecekan data. Jika suatu hari skema /users berubah, cukup ubah di file schema tanpa menyentuh route atau controller. Inilah alasan middleware validasi seperti ini sangat direkomendasikan untuk API Express yang rapi, aman, dan scalable.

 

Kesimpulan

Middleware validasi ini merupakan contoh best practice dalam membangun sistem API yang rapi dan terstruktur. Dengan pendekatan terpusat berbasis schema, proses validasi tidak lagi tersebar di berbagai controller, melainkan dikelola dalam satu lapisan khusus yang reusable. Artinya, kode bisa digunakan ulang di banyak endpoint tanpa duplikasi logika. Dari sisi keamanan, penggunaan Joi membantu memastikan hanya data yang sesuai aturan yang dapat diproses lebih lanjut, sehingga risiko bug dan celah eksploitasi dapat ditekan. Struktur yang fleksibel juga membuat middleware ini mudah dikembangkan, baik untuk menambah schema baru maupun menyesuaikan kebutuhan proyek yang terus berkembang. Pola seperti ini sangat cocok diterapkan pada proyek kecil, menengah, hingga skala besar karena meningkatkan konsistensi dan maintainability. Dengan validasi yang kuat di awal, logic bisnis menjadi lebih bersih, error lebih terkontrol, dan API terlihat jauh lebih profesional serta siap dikembangkan secara scalable.

Series: Nodejs
Published on May 04, 2026
Last updated on June 03, 2026

If you like this post and want to support us, you can support us via buymeacoffee or trakteer.