listWeb Development 101
ลอง Rest API และ Postman
สารบัญ
เราจะมาลองเริ่มต้น hello world api กันแบบง่ายๆก่อน ผมจะขอพารู้จัก 2 อย่างไปพร้อมๆกันคือ
- code hello world ของ express
- โปรแกรม Postman ที่ใช้สำหรับทดสอบ API
Hello world express
เราจะสร้าง API method GET ขึ้นมาหนึ่งตัว path / ขึ้นมา (เดี๋ยวเราจะอธิบายเรื่อง method กันอีกที) โดยเราจะส่งคำว่า Hello world ออกมา
เริ่มต้นเราจะแก้ที่ไฟล์ index.js (ไฟล์เดิมกับตอนบทที่ 7) เปลี่ยนมาเป็น code ตัวนี้แทน
// เรียกใช้ library express ด้วยคำสั่ง require
const express = require('express')
// ประกาศเริ่มต้นการใช้ express
const app = express()
const port = 8000
// สร้าง API path '/' และคืนคำ Hello world ออกมาผ่าน API
app.get('/', (req, res) => {
res.send('Hello World!')
})
// ประกาศgxbf http server ที่ port 8000 (ตามตัวแปร port)
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})อธิบายโครงสร้าง code เพิ่มเติม
- ตรง
app.get()คือการประกาศ path ที่จะเปิดให้ฝั่ง client สามารถยิงเข้ามาได้
Client
หมายถึง application / software ที่ทำให้เกิดการเรียกขึ้นมา (สิ่งนี้เราจะเรียกกันว่า request) ซึ่ง API หลังจากที่ได้รับ request มา จะเกิดการส่งข้อมูลกลับ (สิ่งนี้เราจะเรียกกันว่า response)
สามารถย้อนกลับไปดูภาพในบทก่อนหน้าได้
ซึ่งคำว่า .get() หมายถึงการยิงแบบ method GET เข้ามา (เดี๋ยวจะอธิบายเพิ่มเติมกันตรงหัวข้อ Rest API method ด้านล่าง)
app.get('/', (req, res) => {})parameter 2 ตัวประกอบด้วย- parameter ที่ 1 '/' คือการระบุ path ที่เปิดให้ส่งข้อมูล
- parameter ที่ 2 (req, res) คือ function ที่จะจัดการหลังข้อมูลที่ส่งเข้ามาจาก client (ผ่าน req) โดย ตัวแปร req = request ที่ client (หรือ user) ส่งมา, res = response ที่สามารถกำหนดการส่งออกของ API ได้
- ดังนั้น
res.send('Hello world')คือการส่ง response จาก API กลับออกไปยังฝั่ง Client
ภาพ diagram ตัวอย่างของ code จะหน้าตาเป็นประมาณนี้
ทีนี้เดี๋ยวเราจะมาลองดูผลลัพธ์กันด้วย Postman Platform ที่สามารถจำลองการยิงของ Client ได้
รู้จักกับ Postman
Postman คือ Platform สำหรับการทำ API development ที่สามารถทำและทดสอบ API ได้
สามารถลงได้ผ่าน https://www.postman.com/ ซึ่งมีทุก platform ทั้ง windows, mac os, linux
หลังจากลงเสร็จจะได้หน้าตา postman ประมาณนี้ได้
ถ้าได้หน้าตาประมาณนี้ถือว่าลงโปรแกรมถูกต้องแล้ว
ทีนี้เราจะลองยิง API ที่เราพึ่งสร้างมาอันเมื่อกี้ หลังจากเรา Run server ขึ้นมา path ที่จะสามารถยิงได้คือ http://localhost:8000
ดังนั้นเราจะลอง set Postman คือ
- กด "+" จาก Postman จะเจอหน้าตาใหม่โผล่ขึ้นมา
- set method เป็น "GET" (สามารถเลือกได้จากทางซ้ายของ url)
- ใส่ path http://localhost:8000/ ตรง url ข้างๆ
- เมื่อใส่ทั้งหมดครบให้ลองกด "Send" ดู = เป็นการส่ง request เข้า API หลังจากนั้นจะแสดง response ออกมาผ่าน API
ได้ผลลัพธ์ออกมาตามภาพนี้
ถ้าได้ผลลัพธ์ออกมาแบบนี้ได้แปลว่า
- ✅ http server run ได้อย่างถูกต้องที่ port 8000
- ✅ express ได้สร้าง path '/' ออกมาถูกต้อง และส่ง hello world ออกมาถูกต้อง
- ✅ postman ได้ถูกลงอย่างถูกต้อง
ถือว่าพร้อมสำหรับการลุยในหัวข้อต่อไป
Rest API method และ JSON
ในการทำ Rest API เราจะทำผ่าน HTTP server ซึ่ง HTTP นั้นมีมาตรฐานการส่งข้อมูลอยู่เราเรียกกันว่า "HTTP method" ซึ่งเป็นการระบุการแยก action แต่ละประเภทออกจากกันของฝั่ง client ออกจากกัน ซึ่งปกติ HTTP Method นั้นจะมีตัวที่ใช้กันบ่อยๆ คือ GET, POST, PUT, PATCH, DELETE เราจะมาลองทำความรู้จักแต่ละตัวกันว่าแต่ละ method เหมาะ
1. GET - retrive information
GET Method เป็น method ที่ใช้สำหรับการดึง information ออกมา และเอาจริงๆ การเปิด Browser ออกมา ก็ถือว่าเป็นการ request ด้วย method "GET" เป็น default อยู่แล้ว
สามารถลองเทียบได้จากการเปิด url เดียวกันบน browser ได้ (จะผลลัพธ์เหมือนกับตอนที่เรารัน http server ในบทที่ 7)
ทีนี้ ปัญหาอย่างหนึ่งของการส่งข้อมูล response จาก API กลับมาเป็น text คือ ข้อมูลมันจะส่งได้เพียงข้อมูลชนิดเดียว ถ้าสมมุติเราพยายามดึงข้อมูลสักอย่างหนึ่งที่มีหลากหลาย field เช่น ดึงข้อมูล user คนนั้นออกมา โดยที่จะดึง
- firstname = ชื่อจริง
- lastname = นามสกุล
- age = อายุ
3 ข้อมูลนี้ออกมา pattern response แบบ Text จะไม่สะดวกกับเคสแบบนี้ ดังนั้น pattern ที่เราจะใช้สำหรับ response เราจะใช้เป็น pattern ที่ชื่อว่า "JSON" แทน Text
JSON คืออะไร ?
JSON ย่อมาจาก JavaScript Object Notation เป็น format การส่งที่เลียนแบบ Javascript Object ที่ส่งเป็น Text ที่มีลักษณะเป็น Object แทนที่จะส่งเป็น Text ทั่วไปออกมาแทน ซึ่งเป็นรูปแบบที่ส่งผลทำให้สามารถส่งข้อมูลที่ซับซ้อนให้มีขนาดไม่ใหญ่มาก และทั้งมนุษย์และคอมพิวเตอร์สามารถอ่านออกได้ไม่ยาก จึงเป็น pattern ที่ค่อนข้างเป็นที่นิยมในการใช้ส่งใน API มาก (ทั้งการส่ง request และ การส่ง response)
ตัวอย่าง JSON สมมุติเรามี Javascript Object ที่เก็บข้อมูล firstname (ชื่อจริง), lastname (นามสกุล), age (อายุ)
Javascript Object หน้าตาจะเป็นแบบนี้
{
firstname: 'ทดสอบ',
lastname: 'นามสกุล',
age: 24
}เมื่อเป็น JSON จะมีหน้าตาเป็นประมาณนี้แทน
{"firstname":"ชื่อจริง","lastname":"นามสกุล","age":20}ข้อสังเกต
- ทุก key ของ JSON จะใส่ double quote (แตกต่างกับ object ที่ใส่หรือไม่ใส่ก็ได้)
- ข้อมูลจะทำการย่อให้กลายเป็น text ขนาดก้อนเดียว (แต่ Postman และหลายๆเครื่องมือ มีเครื่องมืออำนวยที่ทำให้เราเห็น JSON ออกมาเป็นเหมือน object ใน javacsript ได้)
เราจะลองปรับ code กันใหม่เป็นแบบนี้แทน
- สร้าง path GET /user โดยจะ return JSON object ที่มี firstname, lastname, age ออกมา
const express = require('express')
const app = express()
// สร้าง GET API path /user
app.get('/user', (req, res) => {
res.json({
firstname: 'ชื่อจริง',
lastname: 'นามสกุล',
age: 20
});
})
const port = 8000
app.listen(port, () => {
console.log(`Server is running on port ${port}`)
})ผลลัพธ์ออกมาหน้าตาแบบนี้
ซึ่งภาพนี้ JSON ได้ถูกแปลง format ให้สวยงามจาก postman แล้ว หากเราอยากดู format จริงๆที่ server response ออกมาให้กดไปที่ Raw ของ Postman ได้ จะเห็นหน้าตาออกมาเหมือนด้านบน
ข้อสังเกต
- เปลี่ยนจาก
res.send()เป็นres.json()แทน เพื่อให้ express ทำการแปลง object ของ javascript ส่งออกมาเป็น JSON ได้
JSON format นั้นเราจะใช้กับการส่งข้อมูลทั้งหมด ไม่ว่าจะเป็นการส่งข้อมูลเข้า server จาก client (request) และ การตอบข้อมูลกลับจาก server (response)
2. POST - create new resource
POST Method เป็น method ที่ใช้สำหรับการเพิ่มข้อมูลเข้าสู่ระบบ ซึ่งจะเป็น Method ที่ทำให้เราส่งข้อมูลผ่าน body เข้ามาได้ (GET จะไม่สามารถทำได้)
ทีนี้ในการส่งข้อมูลเราจะเพิ่ม library อีกตัวขึ้นมา เพื่อให้การส่งข้อมูลผ่าน body จะเป็นการส่งเข้าตัวแปร req ผ่านมายัง key req.body ออกมาได้ (หากไม่ใช้ library นี้ข้อมูล body จะไม่สามารถดึงออกจากตัวแปรนี้ออกมาได้)
ทำการลง library body-parser
npm install body-parserเมื่อลงทุกอย่างถูกต้อง
{
... (ย่อ),
"dependencies": {
"body-parser": "^1.20.2", <-- จะมีตรงนี้เพิ่มมา
"express": "^4.18.2"
}
}เราจะมาลองตัวอย่างง่ายๆกันก่อนโดยการลองส่ง text ผ่าน body
const express = require('express')
const app = express()
const bodyParser = require('body-parser')
app.use(bodyParser.text())
app.post('/test', (req, res) => {
// ดึง data ออกจาก body
const textData = req.body
res.send(textData)
})
app.listen(8000, () => {
console.log('Server started on port 8000')
})ทีนี้เราจะลองเปลี่ยนเป็น JSON และเพิ่ม use case เก็บ users
const express = require('express')
const app = express()
const bodyParser = require('body-parser')
// Parse incoming JSON data
app.use(bodyParser.json())
// เราสร้างตัวแปร users ขึ้นมาเป็น Array จำลองการเก็บข้อมูลใน Server (ซึ่งของจริงจะเป็น database)
let users = []
// Route handler for creating a new user
app.post('/user', (req, res) => {
const data = req.body
const newUser = {
firstname: data.firstname,
lastname: data.lastname,
age: data.age
}
//
users.push(newUser)
// Server ตอบกลับมาว่าเพิ่มแล้วเรียบร้อย
res.status(201).json({ message: 'User created successfully', user: newUser })
})
app.listen(8000, () => {
console.log('Server started on port 8000');
})3. PUT - update existing resource
PUT Method เป็น method ที่ใช้สำหรับการแก้ข้อมูลเดิมในระบบ โดยจะเป็นการเข้าถึงทุก field
ในนี้จะมีการใช้ parameter ที่ส่งมาผ่าน url เพื่อบอกว่าเป็น user คนไหนไ
const express = require('express')
const app = express()
const bodyParser = require('body-parser')
app.use(bodyParser.json())
let users = []
// ใช้สำหรับสร้างก่อน
app.post('/user', (req, res) => { ... (code เดิมกับอันบน) })
// ใช้สำหรับแก้ไข
app.put('/user/:id', (req, res) => {
const id = req.params.id
const data = req.body
const userToUpdate = users.find((user) => user.id === parseInt(id))
if (!userToUpdate) {
return res.status(404).json({ message: 'User not found' })
}
userToUpdate.firstname = data.firstname || userToUpdate.firstname
userToUpdate.lastname = data.lastname || userToUpdate.lastname
userToUpdate.age = data.age || userToUpdate.age
res.json({ message: 'User updated successfully', user: userToUpdate })
})4. PATCH - update only fields in resource
PATCH Method เป็น method ที่ใช้สำหรับการแก้ข้อมูลเดิมในระบบ โดยจะเป็นการเข้าถึงเฉพาะ field ที่ส่งเข้ามาเท่านั้น (แตกต่างกับ PUT ที่ access ทุก field)
const express = require('express')
const app = express()
const bodyParser = require('body-parser')
app.use(bodyParser.json())
let users = []
app.post('/user', (req, res) => { ... (code เดิมกับอันบน) })
// ลองเปลี่ยนจาก put เป็น patch
app.patch('/user/:id', (req, res) => {
const id = req.params.id
const data = req.body
const userToUpdate = users.find((user) => user.id === parseInt(id))
if (!userToUpdate) {
return res.status(404).json({ message: 'User not found' })
}
if (data.firstname) {
userToUpdate.firstname = data.firstname
}
if (data.lastname) {
userToUpdate.lastname = data.lastname
}
if (data.age) {
userToUpdate.age = data.age
}
res.json({ message: 'User updated successfully', user: userToUpdate })
})5. DELETE - delete resource
DELETE Method เป็น method ที่ใช้สำหรับส่งข้อมูลที่ต้องการลบข้อมูล
const express = require('express')
const app = express()
const bodyParser = require('body-parser')
app.use(bodyParser.json())
let users = []
app.post('/user', (req, res) => { ... (code เดิมกับอันบน) })
app.delete('/user/:index', (req, res) => {
const index = req.params.index
// Check if the index is valid
if (index >= 0 && index < users.length) {
// Remove the user at the specified index
const deletedUser = users.splice(index, 1)[0]
res.json({ message: 'User deleted successfully', user: deletedUser })
} else {
res.status(404).json({ error: 'User not found' })
}
})