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

RESTful web service dengan express dan mongodb part 2/2

2
Degananda.com -

Bagian kedua pembuatan RESTful web services ini akan berfokus pada pembuatan kosmetik yang meliputi mengenai : Keamanan , router modular(express) , validasi isi request body dan pengujian. Ke empat hal tersebut diperlukan agar web services dapat memenuhi standar basic , paling tidak dapat digunakan untuk membuat project dalam skala kecil hingga menengah. Jika anda belum mengikuti bagian yang pertama maka disarankan untuk membacannya terlebih dahulu dikarenakan ulasan ini adalah ulasan bersambung.

Silahkan clone repository github dibawah ini (source code web services dengan express dan mongodb) jika anda tidak mengikuti bagian pertama.

https://github.com/degananda/express-mongodb/tree/1.0

1. Http basic auth

Sebuah web services tentunnya akan dikonsumsi atau diakses oleh client. Jika web services tersebut tidak diberikan pengamanan maka web services tersebut dapat dikonsumsi oleh siapa saja. Oleh karena itu membatasi akses terhadap suatu web services sangatlah penting. Terdapat beberapa hal yang dapat dilakukan untuk membatasi akses tersebut contohnya :

  1. Memberikan username dan password saat mengakses endpoint
  2. Membatasi IP Address yang dapat mengakses web services
  3. Menggunakan JWT / PassportJS dan lain sebagainya
  4. Menggunakan modul “Helmet” untuk express

dari ke empat metode tersebut pada ulasan ini akan dibahas cara implementasi http basic auth untuk memberikan username dan password untuk web services kita.

Langkah 1 untuk menerapkan http basic auth adalah menginstall http-auth melalui NPM.

npm install http-auth --save

langkah 2 menginisiasi http-auth serta mengkonfigurasi username dan password

// http auth (basic)
var auth = require('http-auth');
var basic = auth.basic({
        realm: "Who are you?"
    }, (username, password, callback) => { 
        callback(username === "degananda" && password === "indonesiaraya");
    }
);
// Implementasi basic auth pada express
app.use(auth.connect(basic));

done , cukup dua langkah untuk mengimplementasikan basic-auth (http-auth) pada express. Http auth ini juga dapat digunakan pada web framework javascript lainnya seperti koa dan hapi (selain express itu sendiri). Ganti isi dari username dan password dengan yang anda inginkan(secure).

2. Express router modular

Web services tentunnya dapat memiliki banyak sekali endpoint. Pada part-1 kita hanya memiliki satu buah endpoint yakni /note. Bagaimana jika pada web services yang kita buat memiliki lebih dari satu endpoint? tentunnya jika kita letakan seluruh http response dalam sebuah file (index.js/app.js) akan sangat buruk untuk proses manajemen kodenya. Solusinnya adalah membaginnya menjadi modul-modul tertentu.

Langkah pertama adalah buat folder bernama routeModule dan didalamnya buatlah file note.js

langkah kedua tuliskan kode dibawah ini pada note.js

var express = require('express');
var routerList = function(){
    var router = express.Router();
    return router;
};
module.exports = routerList;

kita akan membuat router secara modular. Modul yang diperlukan adalah express (untuk membuat router).  Kemudian kita akan buat satu buah variabel bernama routerList yang akan mereturn variabel yang telah di inisiasikan sebauh router. Kemudian fungsi tersebut akan kita export sebagai module dengna fungsi module.exports.

langkah ketiga migrasi seluruh http response (get/post/put/delete) dari index.js ke note.js (folder route module).

Isi dari note.js adalah sebagai berikut ini.

var express = require('express');
var routerList = function(noteCollection, mongo){
    var router = express.Router();
    // Endpoint : GET
    router.get('/', function(req, res){
        this.noteCollection.find().toArray(function (err, docs){
            res.status(200).json(docs);
        });
    });

    // Endpoint : GET/:id
    router.get("/:id", function(req, res){
        var docId = new mongo.ObjectID(req.params.id);
        this.noteCollection.find({
            "_id" : docId
        }).toArray(function (err, docs){
            res.status(200).json(docs);
        });
    });

    // Endpoint : POST
    router.post('/', function(req, res ){
        this.noteCollection.insert({
            "judul_note" : req.body.judul_note,
            "isi_note" : req.body.isi_note,
            "date_posted" : new Date().getTime()
        }, function(err, result){
            if(!err){
                res.status(200).send('berhasil menambahkan note');
            } else {
                throw err;
            }
        });

    });

    // Endpoint : PUT
    router.put('/:id', function(req, res){
        var docId = new mongo.ObjectID(req.params.id);
        this.noteCollection.update({
            "_id" : docId
        }, {
            "judul_note" : req.body.judul_note,
            "isi_note" : req.body.isi_note,
            "date_updated" : new Date().getTime()
        }, function(err, result){
            if(!err){
                res.status(200).send('berhasil mengubah note');
            } else {
                throw err;
            }
        });
    });

    // Endpoint : DELETE
    router.delete('/:id', function(req, res){
        var docId = new mongo.ObjectID(req.params.id);
        this.noteCollection.remove({
            "_id" : docId
        }, function(err, result){
            if(!err){
                res.status(200).send('berhasil menghapus note');
            } else {
                throw err;
            }
        });
    });

    return router;
};
module.exports = routerList;

pada variabel routerList akan kita tambahkan dua parameter fungsi. Yakni note collection dan mongo. noteCollection digunakan untuk mengambil instances collection yang nantinnya digunakan untuk melakukan query find pada saat http request. Sedangkan mongo digunakan untuk membuat ObjectID.

Langkah ke-empat adalah memanggil note.js pada index.js

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var appPort = process.env.port || 7250;

// http auth (basic)
var auth = require('http-auth');
var basic = auth.basic({
        realm: "Who are you?"
    }, (username, password, callback) => { 
        callback(username === "degananda" && password === "indonesiaraya");
    }
);
// Implementasi basic auth pada express
app.use(auth.connect(basic));

// Gunakan body parser dan menerima json
// agar kita dapat menggunakan req.body (untuk mengambil http request body yang diberikan oleh client/user)
app.use(bodyParser.json());

// Konfigurasi mongodb
var mongo = require('mongodb');
var MongoClient = require('mongodb').MongoClient;

// Connection URL
var url = 'mongodb://localhost:27017/degananda'; // degananda adalah nama database.
var dbConnect;
var noteCollection;
// Use connect method to connect to the Server
MongoClient.connect(url, function(err, db) {
    this.dbConnect = db;
    this.noteCollection = this.dbConnect.collection('note');
    console.log("Connected correctly to server");
});

// import routerModule
var noteRouter = require('./routeModule/note.js')(noteCollection, mongo);

// use routerModule
app.use('/note', noteRouter);

app.listen(appPort , function(){
    console.log('apps running on : ' + appPort);
});

setelah seluruh http request kita migrasikan ke note.js maka kita gunakan fungsi app.use(‘/endpoint’,routemodul)(parameter1)(parameter2) dan kita isi parameter yang dibutuhkan. Kita masukan noteCollection dan mongo sesuai yang kita definisikan pada note.js. Intinnya parameter tersebut akan mengakomodasi hal-hal yang dibutuhkan oleh http request dalam hal ini karena kita menggunakan mongodb yang pasti dibutuhkan adalah instances-intances terkait collection / database / object dari mongo itu sendiri. Jika menggunakan mysql maka yang dibutuhkan adalah intances terkait dengan mysql.

tahapan mengenai pemasangan route modular selesai pada tahap ketiga ini.  Jika ingin menambahkan routeModule baru cukup copy dan paste file .note.js ubah dalamnya lalu konfigurasi routemodule tersebut pada index.js sama persis dengan ketiga tahapan yang kita lakukan sebelumnya. Sehingga anda dapat memiliki source code web services yang sangat mudah untuk dikelola(karena dibagi berdasarkan modul-modul).

validasi dengan menggunakan express-validator

Setiap http request body tentunnya harus kita format dan filter sesuai kondisi. Pada kasus kali ini yang akan kita validasi adalah

  1. Tidak boleh ada request body yang bernilai “null”. Misalkan pada endpoint “POST” yang dibutuhkan adalah req.body.judul_note dan req.body.isi_note maka kedua request body tersebut harus ada. Jika tidak ada akan memberikan pesan.

kita hanya menerapkan satu rule saja. Jika anda ingin menambahkan rule-rule yang lain silahkan.

langkah pertama install express-validator melalui npm

npm install express-validator

langkah kedua menggunakan express validator

kita harus menampatkan kode penggunaan express validator(app.use(expressValidator)) setelah penggunaan body parser. Sehingga express-validator ini memiliki requirement berupa “body-parser” tanpa body-parser express-validator tidak dapat dijalankan

// Gunakan body parser dan menerima json
// agar kita dapat menggunakan req.body (untuk mengambil http request body yang diberikan oleh client/user)
app.use(bodyParser.json());

// menggunakan express validator
app.use(expressValidator());

langkah ketiga mengimplementasikan validasi pada http request.

cara melakukan validasi pada express-validator adalah menggunakan req.assert. Berikut adalah daftar metode validasi yang dapat dilakukan dengan menggunakan express-validator.

isEmpty() Untuk memvalidasi apakah nilai null atau tidak
isEmail() Untuk memvalidasi apakah nilanya valid seperti format email.
isInt() Untuk memvalidasi apakah nilai berupa integer

daftar lengkap mengenai tipe validasi dapat dicek digithub resmi express-validator dibawah ini

https://github.com/ctavan/express-validator

berikut ini adalah contoh implementasi express-validator pada http post pada endpoint “/note”.

    // Endpoint : POST
    router.post('/', function(req, res ){
        req.assert('judul_note', 'isi_note belum terdefinisi').notEmpty();
        req.assert('isi_note', 'isi_note belum terdefinisi').notEmpty();
        var validationErrors = req.validationErrors();
        if(!validationErrors){
            this.noteCollection.insert({
                "judul_note" : req.body.judul_note,
                "isi_note" : req.body.isi_note,
                "date_posted" : new Date().getTime()
            }, function(err, result){
                if(!err){
                    res.status(200).send('berhasil menambahkan note');
                } else {
                    throw err;
                }
            });
        } else {
            res.status(400).send(validationErrors);           
        }
    });

kita akan menggunakan fungsi req.assert() dan metode validasi notEmpty() pada req.body.isi_note dan req.body.judul_note.

hasil dari pembangunan web service sini anda dapat akses di :

https://github.com/degananda/express-mongodb