lifelong learner — urip iku urup, currently working on accenture.

Membuat restful API dengan hapi dan mysql

2
Degananda.com -

introduction

Pada tutorial ini akan dibahas mengenai pembuatan RESTful API dengan menggunakan Nodejs, Hapi dan mysql. Sebelum mengikuti tutorial ini pastikan anda telah familiar dengan NodeJS. Ada beberapa hal yang harus disiapkan untuk membuat RESTful API menggunakan hapi ini yaitu :

  1. NodeJS
    kami menggunakan versi 6.9.2
  2. Nodemon
    digunakan untuk mempermudah coding (otomatis menjalankan nodejs kembali ketika terjadi perubahan pada koding)
  3. Mysql (database)
  4. Hapi
    jika anda ingin menggunakan express maka kami memiliki tutorial membuat RESTful API dengan menggunakan express di : https://degananda.com/2017/05/22/node-rest-api-dengan-mysql/
  5. Mysql native driver untuk nodejs

untuk mempermudah mengikuti tutorial ini kami membuat repository pada github sehingga anda dapat dengan mudah mendapatkan/clone source code yang digunakan pada tutorial ini. berikut ini adalah link githubnya.

https://github.com/degananda/hapi-mysql

Web services yang akan dibuat pada ulasan ini memanipulasi data “note” atau catatan. Sebuah catatan memiliki isi dari note dan juga tanggal pembuatan dari catatan tersebut. Fungsi yang akan dicakup adalah :

  1. Menambahkan note baru dengan menggunakan http post
  2. Mengubah note yang sudah ada dengan menggunakan http put
  3. Menghapus note yang telah ada dengan menggunakan http delete
  4. Melihat note dengan menggunakan http get

tabel yang akan digunakan untuk mengakomodasi web services diatas tertera dibawah ini, atau jika anda melakukan clone repository hapi-mysql dari github kami diatas maka sql ini terdapat pada file data_table.sql

--
-- Table structure for table `note`
--
 
CREATE TABLE IF NOT EXISTS `note` (
`id_note` int(11) NOT NULL,
  `isi_note` text NOT NULL,
  `tanggal_note` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 
--
-- Indexes for dumped tables
--
 
--
-- Indexes for table `note`
--
ALTER TABLE `note`
 ADD PRIMARY KEY (`id_note`);
 
--
-- AUTO_INCREMENT for dumped tables
--
 
--
-- AUTO_INCREMENT for table `note`
--
ALTER TABLE `note`
MODIFY `id_note` int(11) NOT NULL AUTO_INCREMENT;

Pembuatan web service

langkah 1 : inisiasi project node

npm init

langkah 2 : konfigurasi project node

setelah package.json tergenerate maka konfigurasi sesuai dengan keinginan anda. Namun jika tidak ingin mengkonfigurasi gunakan setingan default(tekan enter seluruh pertanyaan yang muncul dikonsole anda)

langkah 3 : menginstall beberapa package yang dibutuhkan

hapi

npm install hapi --save

mysql native driver untuk nodejs

npm install mysql --save

setelah melakukan install melalui npm , maka package.json anda akan terupdate. Jika tidak terupdate maka ada yang salah dengan proses installasi

langkah 4 : membuat index.js

buat file index.js atau sesuaikan dengan konfigurasi package.json anda (yang dikonfigurasi saat melakukan npm init pada langkah pertama).

langkah 5 : memanggil package

kita akan memanggil dua package yang telah kita install yakni hapi dan mysql

// RESTful API Hapi + Mysql
// memanggil instances hapi
var hapi = require('hapi');
var mysql = require('mysql');

langkah 6 : membuat instances hapi

buat instances server dari hapi  dan konfigurasi http tersebut akan berjalan dengan nama host dan nomor port yang akan digunakan.

// membuat server dan konfigurasi http
var hapiServer = new hapi.Server();
hapiServer.connection({
    host : 'localhost',
    port : 7728 
});

langkah 7 : konfigurasi mysql dan connect

melakukan konfigurasi mysql , yang diset adalah :

  1. hostname , jika dilocal maka hostname adalah localhost)
  2. user , user dari mysql anda / database
  3. password , password dari user (jika ada)
  4. database , database yang digunakan. Jangan lupa untuk membuat database dan mengimport data_table.sql atau gunakan sql diatas (* pada awal tutorial).
// mysql settings
var connection = mysql.createConnection({
    host     : 'localhost',
    user     : 'root',
    password : '',
    database : 'db_scriptsi'
});
 
connection.connect(function(err){
if(err){
    console.log('something wrong with mysql database connection');
    connection.end();
}
});

langkah 8 : membuat router dari hapi

langkah delapan ini merupakan yang paling utama dalam membuat webservice ini. Kita akan mendefinisikan routing dan handler pada masing-masing route sesuai dengan spesifikasi web services yang akan kita buat. Spesifikasi dari web service kita yaitu :

  1. /note – METHOD GET untuk mendapatkan semua data note pada tabel
  2. /note/{id} – METHOD GET untuk mendapatkan data note sesuai dengan id
  3. /note – METHOD POST untuk menambahkan data note baru ke tabel dengan request body berupa “isi_note”
  4. /note/{id} – METHOD PUT untuk mengubah data note pada tabel sesuai dengan id , dan diubah sesuai dengan request body. isi request body yaitu : “isi_note”
  5. /note/{id} – METHOD DELETE untuk menghapus data note pada tabel sesuai dengan id

kode router dan handler untuk lima kasus diatas adalah seperti berikut ini (file : note.js) :

var routerModule = function(hapiServer,connection){

    hapiServer.route([
        {
            // router get note (all)
            method : 'GET',
            path : '/note',
            handler : function(req, res){

                // mendapatkan id_note , isi_note dan tanggal_note dari tabel note
                var query = "SELECT id_note, isi_note, tanggal_note FROM note ORDER BY tanggal_note DESC";
                connection.query(query, function(err, result, fields){
                    if(err){
                        // jika error maka throw errornya.
                        throw err;
                    } else {
                        if(result.length > 0){
                            // jika teradpat data maka, hasil dari query akan diberikan.
                            const response = res(result);
                            response.type('application/json');
                        } else {
                            // jika tidak ada data menampilkan pesan.
                            const response = res({
                                msg : "tidak ada data note pada database"
                            });
                            // response bertipe application/json
                            response.type('application/json');
                        }
                    }
                });

            } // end handler
        },
        {
            // router get single note
            method : 'GET',
            path : '/note/{id}',
            handler : function(req, res){
                
                var id = req.params.id;
                // mendapatkan id_note , isi_note dan tanggal_note dari tabel note
                var query = "SELECT id_note, isi_note, tanggal_note FROM note WHERE id_note = "+id+" ORDER BY tanggal_note DESC";
                connection.query(query, function(err, result, fields){
                    if(err){
                        // jika error maka throw errornya.
                        throw err;
                    } else {
                        if(result.length > 0){
                            // jika teradpat data maka, hasil dari query akan diberikan.
                            const response = res(result);
                            response.type('application/json');
                        } else {
                            // jika tidak ada data menampilkan pesan.
                            const response = res({
                                msg : "tidak ada data note pada database"
                            });
                            // response bertipe application/json
                            response.type('application/json');
                        }
                    }
                });


            } // end handler
        },
        {
            // router add note
            method : 'POST',
            path : '/note',
            handler : function(req, res){

                // payload digunakan untuk mengambil isi dari http body
                if(typeof req.payload.isi_note !== "undefined"){
                    var query = "INSERT INTO NOTE(isi_note,tanggal_note) VALUES('"+req.payload.isi_note+"', NOW())";
                    connection.query(query, function(err, result, fields){
                        if(err){
                            throw err;
                        } else {
                            // berhasil menambahkan note.
                            const response = res({
                                msg : "berhasil menambahkan note baru"
                            });
                            // response bertipe application/json
                            response.type('application/json');
                        }
                    });
                } else {
                    const response =  res({
                        msg : "required body not defined"
                    });
                    response.type('application/json');                    
                }

            } // end handler
        },
        {
            // router delete  note
            method : 'DELETE',
            path : '/note/{id}',
            handler : function(req, res){

                var id = req.params.id;
                var query = "DELETE FROM note where id_note = '"+id+"'";
                connection.query(query, function(err, result, fields){
                    if(err){
                        throw err;
                    } else {
                        if(fields){
                            const response = res({
                                msg : "berhasil menghapus note."
                            });
                            response.type('application/json');                    
                        } else {
                            const response = res({
                                msg : "tidak ada data note"
                            });
                            response.type('application/json');                    
                        }
                    }
                });

            } // end handler
        },
        {
            // router edit  note
            method : 'PUT',
            path : '/note/{id}',
            handler : function(req, res){ 

                if(typeof req.payload.isi_note !== "undefined"){

                    var query = "UPDATE note SET isi_note = '"+req.payload.isi_note+"', tanggal_note=NOW() WHERE id_note = '"+req.params.id+"'";
                    connection.query(query, function(err, result, fields){
                
                        if(err){
                            const response = res({
                                msg : "gagal mengubah note."
                            });
                            response.type('application/json');   
                        } else{
                            const response = res({
                                msg : "berhasil mengubah note."
                            });
                            response.type('application/json');   
                        }
                
                    });
                
                } else {

                    const response = res({
                        msg : "required body not defined"
                    });
                    response.type('application/json');  

                }


            } // end handler
        }
    ]);

}

module.exports = routerModule;

dapat kita lihat bahwa kami menggunakan dua buah instances yakni hapiServer dan connection. Dua instances tersebut kita dapatkan dari file index.js. Kode diatas merupakan isi dari note.js yang merupakan router module yang letaknya terpisah dari index.js. Pemisahan router ini ditujukan agar memudahkan dalam membaca project dan memaintain kode. bayangkan jika seluruh router kita letakan pada index.js maka sangat membingunkan.

var routerModule = function(hapiServer,connection){

hapiServer adalah instances yang digunakan untuk membuat router, sedangkan connection adalah instances koneksi mysql untuk melakukan query. Fungsi query pada instances connection yang kita berikan(pass) dari index.js ke router module(note.js) memiliki tiga buah callback yaitu :

  1. err -> callback yang berisi informasi mengenai error, misalnya terjadi sql query maka informasi error akan tersimpan pada callback ini
  2. fields -> callback yang menginformasikan apakah ada respon dari database mysql. Sejauh yang saya tahu fields akan kosong ketika tidak terdapat data yang dihasilkan oleh sql query. Sehingga cocok untuk menfilter apakah query tersebut match dengan data yang ada atau tidak.
  3. result -> hasil dari sql query akan disimpan disini.

langkah 9 : memanggil router module dan menjalankan hapi

ini adalah langkah terahir, yang perlu kita lakukan hanyalah memanggil router module yang telah kitabuat(note.js) ke index.js(“rootmodule“) dengan menggunakan fungsi require, dan secara otomatis router tersebut dapat berjalan dihapi. Setelah itu, kita jalankan server hapi sesuai dengan konfigurasi host dan port yang telah kita tentukan

// route list
var noteRouter = require('./routerModule/note.js')(hapiServer,connection);

// menjalankan hapi
hapiServer.start(
    function(err){
        console.log("hapi berjalan pada port" +  hapiServer.info.port)
    }
);

selesai, maka RESTful API web services kita siap digunakan. Untuk menjalankan project node ini kami menggunakan nodemon (agar saat terjadi perubahan kode , node otoamtis ter-reload) :

nodemon ./index.js localhost 7728