Terakhir diperbaharui: Oct 24, 2020
Design REST API
Daftar Isi
Tabel CRUD Project Setup REST API Testing menggunakan Postman Koneksi Database Menambahkan Route Handler - Create - Read - Update - Delete - Final CodeTabel CRUD
Kita buat sebuah tabel untuk menjelaskan detail operasi CRUD yang ada di REST API:
Operasi | HTTP Method | URL | URL Params |
---|---|---|---|
Create | POST | /note | |
Read (satu note) | GET | /note | :id |
Read (semua note) | GET | /notes | |
Update | PUT | /note/:id | |
Delete | DELETE | note/:id |
Project Setup
Step by step
- Buka terminal kemudian clone Repository Front End dari DinoTes
1$ git clone https://github.com/devsaurus-class/dinotes-app.git
- Pindah ke dalam direktori dinotes-app dan install dependencies
1$ cd dinotes-app2$ yarn install
- Di dalam folder dinotes-app buat sebuah folder dengan nama api.
Struktur folder:
1(dinotes - app) | --api | --node_modules | --public | --src;
- Tambahkan package express ke dalam project
1$ yarn add express
- Buat sebuah Express app
Buat sebuah file bernama server.js di dalam folder api dan salin code berikut:
1const express = require('express');2const app = express();3const port = 3001;45app.listen(port, () => {6 console.log(`REST API listening at http://localhost:${port}`);7});
Pada code di atas kita membuat sebuah aplikasi express yang aktif di port 3001. Perlu diingat bahwa front end dari dinotes menggunakan port 3000, oleh karena itu kita gunakan port lain selain port 3000, tidak harus 3001.
Untuk menjalankan aplikasi express di atas eksekusi perintah node ./api/server.js
Development
Untuk melihat hasil dari setiap perubahan yang kita buat pada aplikasi express kita harus me-restart aplikasi secara manual. Hal ini sedikit merepotkan.
Kita bisa gunakan package bernama nodemon untuk membantu kita me-restart aplikasi secara otomatis setiap kali ada perubahan.
Tambahkan package nodemon ke dalam project.
1$ yarn add global nodemon
Dengan perintah di atas package nodemon akan ditambahkan secara global, sehingga nodemon akan tersedia di system path dan kita bisa memanggilnya di terminal. Perintah ini sama dengan npm install -g nodemon
.
Selanjutnya untuk menjalankan aplikasi express kita bisa gunakan perintah:
1$ nodemon ./api/server.js
Atau kamu bisa navigasi ke folder api kemudian eksekusi perintah
1$ nodemon server.js
REST API
Untuk permulaan setiap HTTP method yang dipanggil hanya akan menampilkan sebuah pesan bukan data.
Contoh:
request GET yang diterima server akan direspon dengan pesan Received a GET request.
POST
- Menambahkan note
Sekarang kita tambahkan sebuah route untuk menghandle POST request yang diarahkan ke url /note
.
1const express = require('express');2const app = express();3const port = 3001;45app.post('/note', (req, res) => {6 res.send('Received a POST request');7});89app.listen(port, () => {10 console.log(`Server listening at http://localhost:${port}`);11});
Untuk menguji route yang sudah dibuat, kita bisa menggunakan sebuah aplikasi sederhana bernama curl, yang umumnya sudah terinstall pada Operating System.
curl adalah command-line tool yang digunakan untuk mengirim data via URL dan support puluhan protokol termasuk protokol HTTP.
Jika kamu menggunakan windows mungkin kamu harus menginstallnya secara manual. Kamu bisa download di sini.
Buka terminal dan jalankan perintah berikut ini:
1$ curl -X POST http://localhost:3001/note
Hasilnya:
Selanjutnya kita tambahkan route method yang lain:
GET
- Mendapatkan semua notes
1app.get('/notes', (req, res) => {2 res.send('Receive GET request');3});
- Mendapatkan satu note
1app.get('/note/:id', (req, res) => {2 res.send('Received GET request with parameter');3});
PUT
- Update note
1app.put('/note/:id', (req, res) => {2 res.send('Received PUT request');3});
DELETE
- Hapus note
1app.delete('/note/:id', (req, res) => {2 res.send('Received DELETE request');3});
Code server.js:
1const express = require('express');23const app = express();4const port = 3001;56app.post('/note', (req, res) => {7 res.send('Receive POST request');8});910app.get('/notes', (req, res) => {11 res.send('Receive GET request');12});1314app.get('/note/:id', (req, res) => {15 res.send('Received GET request with parameter');16});1718app.put('/note/:id', (req, res) => {19 res.send('Received PUT request');20});2122app.delete('/note/:id', (req, res) => {23 res.send('Received DELETE request');24});2526app.listen(port, () => {27 console.log(`Server listening at http://localhost:${port}`);28});
Output yang didapatkan menggunakan curl:
Meskipun curl dapat digunakan untuk menguji REST API, curl memiliki beberapa keterbatasan. Salah satunya adalah menguji metode POST dengan data berjumlah banyak dan bersifat kompleks menggunakan curl bukanlah sesuatu yang mudah.
Oleh karena itu kita akan menggunakan API testing tools. Salah satu API testing tool yang sering digunakan oleh developer adalah Postman.
Testing menggunakan Postman
Postman adalah salah satu tool yang banyak digunakan developer dalam mengembangkan sebuah API.
Dengan postman kita bisa membuat, menguji dan memodifikasi API dengan mudah.
Pada bagian ini kita akan menggunakan Postman untuk menguji API yang sudah kita buat.
Install
Download Postman disini kemudian install.
Tampilan Postman setelah install (bisa berbeda tergantung versi).
Penggunaan
Menggunakan postman untuk test REST API:
Step by step
- Buat sebuah collection baru
Klik tombol New -> Pilih Collection -> Beri nama collection dinotes-api (atau pilih nama sesuai keinginan) -> Klik Create
Atau kamu bisa pilih menu Create Collection dari Launchpad
- Buat sebuah request baru
Klik tombol New -> Pilih Request -> Beri nama request get notes -> Simpan di collection dinotes-api -> Klik Create
Jenis request yang kita buat adalah GET, pastikan memilih GET pada menu drop down yang tersedia.
- Masukan url endpoint http://localhost:3000/notes kemudian klik Send
Hasilnya
Kita bisa ulangi langkah di atas untuk menguji url endpoint dengan HTTP method yang lain (POST, PUT, DELETE).
Postman menyediakan banyak opsi yang bisa digunakan untuk mempermudah kita melakukan testing API, seperti menambahkan Query Params, Authorization, Headers atau Body pada sebuah request.
Koneksi Database
Saatnya menambahkan database untuk mengelola data yang ditransfer via API.
Database yang kita gunakan adalah NoSQL database MongoDB.
Persiapan
- Install MongoDB, instruksinya bisa dilihat disini
- Install Database Management Tool MongoDB Compass
Buat Database & Collection
Kita perlu membuat sebuah Database dan satu Collection untuk menyimpan data yang dikirim ke server via API.
Kita bisa memanfaatkan MongoDB compass untuk membuatnya dengan mudah.
Step by step
- Jalankan MongoDB compass
- Pada bagian New Connection, klik button CONNECT
MongoDB compass akan menyediakan informasi koneksi ke MongoDB yang sudah terinstall di komputer/localhost, sehingga kita tinggal klik button CONNECT
- Setelah terhubung, klik button CREATE DATABASE untuk membuat database baru
- Beri Nama database dinotesDB dan nama Collection notes, kemudian klik CREATE DATABASE
Hasilnya:
Membuat Koneksi
Untuk dapat menggunakan MongoDB di Node.js kita butuh menambahkan package MongoDB driver.
Step by step
- Install MongoDB driver
1$ yarn add mongodb
- Buat koneksi ke MongoDB database
Update code api/server.js
1const express = require('express');2const { MongoClient } = require('mongodb');34const app = express();5const port = 3001;67// Database89// Connection URL10const url = 'mongodb://localhost:27017';1112// Database Name13const dbName = 'dinotesDB';1415// Connect to database16MongoClient.connect(url, (err, client) => {17 console.log('Connected successfully to server');1819 const db = client.db(dbName);2021 client.close();22});2324// Routes2526app.post('/note', (req, res) => {27 res.send('Receive POST request');28});2930app.get('/notes', (req, res) => {31 res.send('Receive GET request');32});3334app.get('/note/:id', (req, res) => {35 res.send('Received GET request with parameter');36});3738app.put('/note/:id', (req, res) => {39 res.send('Received PUT request');40});4142app.delete('/note/:id', (req, res) => {43 res.send('Received DELETE request');44});4546app.listen(port, () => {47 console.log(`Server listening at http://localhost:${port}`);48});
Penjelasan:
mongodb://localhost:27017
adalah alamat MongoDB server yang terinstall di komputer, by default MongoDB server menggunakan port 27017const dbName='dinotesDB'
, dinotesDB adalah nama dari databaseMongoClient.connect(...)
adalah method yang digunakan untuk membuat koneksi ke MongoDB server
Jika muncul pesan Connected successfully to server pada console maka server sudah berhasil connect ke MongoDB.
Menambahkan Route Handler
Selanjutnya kita akan membuat handler untuk masing-masing route.
Agar server dapat mengakses data yang ada di dalam body sebuah request kita perlu menambahkan middleware body-parser.
Step by step
- Install package body-parser:
1$ yarn add body-parser
- Tambahkan middleware sebelum routes
1const express = require('express');2const { MongoClient } = require('mongodb');3const bodyParser = require('body-parser');45const app = express();6const port = 3001;78// Connection URL9const url = 'mongodb://localhost:27017';10// Database Name11const dbName = 'dinotesDB';1213app.use(bodyParser.urlencoded({ extended: true }))1415// Routes16...
Create
- Tambahkan code berikut ke file api/server.js.
1const express = require('express');2const { MongoClient } = require('mongodb');3const bodyParser = require('body-parser');45const app = express();6const port = 3001;78// Connection URL9const url = 'mongodb://localhost:27017';10// Database Name11const dbName = 'dinotesDB';1213app.use(bodyParser.urlencoded({ extended: true }));1415// Routes1617app.post('/note', (req, res) => {18 // Buat koneksi ke server19 MongoClient.connect(url, (err, client) => {20 const db = client.db(dbName);21 const notesCollection = db.collection('notes');2223 // Simpan data ke collection notes24 notesCollection.insertOne(req.body).then((result) => {25 // tampilkan hasilnya di console26 console.log(result);27 });2829 // tutup koneksi ke database30 client.close();31 });3233 // kirim status dan pesan dalam format json ke client34 res.status(200).json('Data successfully saved');35});3637app.get('/notes', (req, res) => {38 res.send('Receive GET request');39});4041app.get('/note/:id', (req, res) => {42 res.send('Received GET request with parameter');43});4445app.put('/note/:id', (req, res) => {46 res.send('Received PUT request');47});4849app.delete('/note/:id', (req, res) => {50 res.send('Received DELETE request');51});5253app.listen(port, () => {54 console.log(`Server listening at http://localhost:${port}`);55});
Penjelasan
Ketika sebuah POST request diterima oleh server, handler akan membuat koneksi ke MongoDB kemudian data yang ada di dalam req.body akan dimasukan ke dalam collection.
Testing
Mari kita lakukan testing menggunakan Postman.
- Buka Postman
- Buat Request baru
- Pilih POST kemudian masukan url http://localhost:3001
- Pada tab Body isikan data berikut sebagai simulasi data yang berasal dari front-end DinoTes
title | note |
---|---|
What is dinosaur ? | Dinosaurs are a class of extinct reptiles and modern birds of the clade Dinosauria |
- Klik Send
Jika berhasil dan tidak ada error hasilnya akan seperti ini:
- Postman
- MongoDB Compass
Kita akan lanjutkan untuk menambah handler untuk route yang lain.
Tambahkan lebih banyak data ke dalam colection.
Kita bisa gunakan Mock Data Generator seperti Mockaroo untuk mendapatkan sample data yang akan ditambahkan ke collection lewat MongoDB Compass.
- Generate Data menggunakan Mockaroo
- Download data dalam bentuk CSV
- Pada MongoDB Compass, klik ADD DATA -> Import File -> Pilih file CSV yang sudah kita download sebelumnya
Read
Update /api/server.js dengan code berikut untuk menghandle GET request
- Cari semua notes
1...23app.get('/notes', (req, res) => {4 MongoClient.connect(url, (err, client) => {5 const db = client.db(dbName);6 const notesCollection = db.collection('notes');78 // Read all data9 notesCollection10 .find()11 .toArray()12 .then((result) => {13 res.status(200).json(result);14 });1516 client.close();17 });18});1920...
Mencari semua notes dilakukan dengan menggunakan metode notesCollection.find()
, namun hasil pencarian dari method ini adalah sebuah cursor yang sulit dibaca.
Oleh karena itu kita perlu menggunakan method toArray()
untuk mengubahnya menjadi document sehingga lebih mudah untuk dibaca.
- Cari satu note sesuai id
1const { MongoClient, ObjectId } = require('mongodb');23...45app.get('/note/:id', (req, res) => {6 MongoClient.connect(url, (err, client) => {7 const db = client.db(dbName);8 const notesCollection = db.collection('notes');910 // cari note sesuai id11 notesCollection12 .findOne({ '_id': ObjectId(req.params.id) })13 .then((result) => {14 res.status(200).json(result);15 });1617 client.close();18 });19});2021...
Gunakan req.params untuk mendapatkan parameter yang ada di url.
Update
Update /api/server.js dengan code berikut untuk menghandle PUT request
1...23app.put('/note/:id', (req, res) => {4 MongoClient.connect(url, (err, client) => {5 const db = client.db(dbName);6 const notesCollection = db.collection('notes');78 // update data collection9 notesCollection10 .updateOne(11 { _id: ObjectId(req.params.id) },12 { $set: { title: req.body.title, note: req.body.note }}13 ).then((result) => {14 console.log(result);15 });1617 client.close();18 });1920 res.status(200).json('Data successfully updated');21});2223...
Selain method updateOne()
kita juga bisa menggunakan method findOneAndUpdate()
.
Letak perbedaannya ada pada output yang dihasilkan(return). findOneAndUpdate()
akan return document yang baru saja diupdate sedangkan updateOne()
tidak.
Delete
Update /api/server.js dengan code berikut untuk menghandle DELETE request
1...23app.delete('/note/:id', (req, res) => {4 MongoClient.connect(url, (err, client) => {5 const db = client.db(dbName);6 const notesCollection = db.collection('notes');78 // update data collection9 notesCollection10 .deleteOne({ _id: ObjectId(req.params.id) })11 .then((result) => {12 console.log(result);13 });1415 client.close();16 });1718 res.status(200).json('Data successfully deleted');19});2021...
Final Code
1/* eslint-disable no-console */2const express = require('express');3const { MongoClient, ObjectId } = require('mongodb');4const bodyParser = require('body-parser');56const app = express();7const port = 3001;89// Connection URL10const url = 'mongodb://localhost:27017';11// Database Name12const dbName = 'dinotesDB';1314app.use(bodyParser.urlencoded({ extended: true }));1516// Routes1718app.post('/note', (req, res) => {19 MongoClient.connect(url, (err, client) => {20 const db = client.db(dbName);21 const notesCollection = db.collection('notes');2223 // Insert data to collection24 notesCollection.insertOne(req.body).then((result) => {25 console.log(result);26 });2728 client.close();29 });3031 res.status(200).json('Data successfully saved');32});3334app.get('/notes', (req, res) => {35 MongoClient.connect(url, (err, client) => {36 const db = client.db(dbName);37 const notesCollection = db.collection('notes');3839 // Insert data to collection40 notesCollection41 .find()42 .toArray()43 .then((result) => {44 res.status(200).json(result);45 });4647 client.close();48 });49});5051app.get('/note/:id', (req, res) => {52 MongoClient.connect(url, (err, client) => {53 const db = client.db(dbName);54 const notesCollection = db.collection('notes');5556 // cari note sesuai id57 notesCollection.findOne({ _id: ObjectId(req.params.id) }).then((result) => {58 res.status(200).json(result);59 });6061 client.close();62 });63});6465app.put('/note/:id', (req, res) => {66 MongoClient.connect(url, (err, client) => {67 const db = client.db(dbName);68 const notesCollection = db.collection('notes');6970 // update data collection71 notesCollection72 .updateOne({ _id: ObjectId(req.params.id) }, { $set: { title: req.body.title, note: req.body.note } })73 .then((result) => {74 console.log(result);75 });7677 client.close();78 });7980 res.status(200).json('Data successfully updated');81});8283app.delete('/note/:id', (req, res) => {84 MongoClient.connect(url, (err, client) => {85 const db = client.db(dbName);86 const notesCollection = db.collection('notes');8788 // update data collection89 notesCollection.deleteOne({ _id: ObjectId(req.params.id) }).then((result) => {90 console.log(result);91 });9293 client.close();94 });9596 res.status(200).json('Data successfully deleted');97});9899app.listen(port, () => {100 console.log(`Server listening at http://localhost:${port}`);101});
Tapi sekarang code menjadi sangat panjang.
Waktunya Refactoring...