มาทำ RESTFul API ด้วย Node.js กับ Express กันดีกว่า

Published on
NodeJS
2014/09/restful-api-with-node-js-and-express
Discord

บทความนี้ไม่ได้อัพเดท แนะนำอ่านบทความล่าสุดครับ ทำ Backend API ด้วย Node.js และ MongoDB กันดีกว่า

บทความนี้จะมาพูดถึงด้าน Web Development นะครับ นั่นก็คือ Node.js และ Express.js ซึ่งจริงๆ ตัวอย่างนี้ ผมจะไม่มีพูดถึงรายละเอียดเชิงลึก หรือทฤษฎีอะไรมากมายนะครับ เพียงแค่นำเสนอตัวอย่าง และวิธีการทำ RESTFul API ด้วย Node.js จากประสบการณ์ที่ผมทำมาเท่านั้น ซึ่งผมก็ยังเพิ่มเริ่มศึกษา หากส่วนไหนผิดพลาด ก็ต้องขออภัยด้วยนะครับ

เป้าหมายของบทความนี้คือ RESTFul API ฉะนั้น ผม assume ว่าผู้อ่าน มีพื้นฐานด้านการเขียนเว็บแล้ว เพราะฉะนั้นก็จะไม่พูดถึงพื้นฐานมากนัก ส่วนไหน ไม่รู้ก็หาอ่านเพิ่มเติมเอาเองนะครับ

ลิงค์นี้คือตัวอย่าง ที่ผมลองเขียนไว้ใน Runnable ครับ เพิ่งจะว่างมาทำบทความ ก็วันนี้แหละ :D

Step 1 : Install Node.js

สำหรับวิธีการติดตั้ง Node.js หรือรายละเอียดอื่นๆ ขอข้ามเลยละกัน assume ่ว่าผู้อ่านทุกคน ติดตั้ง Node.js ไว้ในเครื่องเรียบร้อยแล้ว ข้างล่างนี้คือ รายละเอียด เอาไว้สำหรับอ่านเพิ่มเติมนะครับ สำหรับติดตั้ง และคนที่ยังไม่รู้ว่า Node.js คืออะไร

Step 2 : Create Project

ก่อนที่จะเริ่มสร้างโปรเจ็ค ลองทำการทดสอบว่าติดตั้ง Node.js และ npm ไว้เรียบร้อยแล้ว

node --version
v0.10.29

npm --version
1.4.14

ต่อมา ทำการสร้างโปรเจ็คขึ้นมา สามารถสร้างแบบ Manual โดยการสร้างไฟล์ชื่อ package.json หรือว่าจะใช้คำสั่ง npm init ก็ได้ครับ ตัวอย่างผมใช้ npm init จะมีขั้นตอนมาให้เราใส่รายละเอียด เมื่อตั้งค่าเรียบร้อย จะได้ไฟล์ package.json หน้าตาประมาณนี้

{
  "name": "devahoy-nodejs",
  "version": "0.0.1",
  "description": "Devahoy Node.js with Express 4 Tutorial",
  "main": "index.js"
}

ตัว package.json มันเป็นเสมือนบัตรประจำตัวของโปรเจ็คนั้นๆ ที่จะระบุว่า โปรเจ็คนั้นชื่อว่าอะไร มีเวอร์ชันที่เท่าไหร่ รายละเอียดอะไรบ้าง ต้องใช้ Dependencies อะไรบ้าง อื่นๆ อีกเยอะแยะ

ต่อมา ติดตั้ง Express ด้วยคำสั่ง (หากติด permission ให้ใช้ sudo )

npm install express --save

--save คือการระบุ ให้ติดตั้ง พร้อมกับเซฟค่าไว้ใน package.json ด้วย เวลาที่เราย้ายโฟลเดอร์ ก็สามารถติดตั้ง dependencies ได้ง่ายๆ ด้วยคำสั่ง npm install ไม่ต้องมา npm install xxxx แยกทีละโปรเจ็คให้ยุ่งยาก และเสียเวลา

เมื่อติดตั้ง เสร็จ จะได้ผลลัพธ์ลักษณะนี้

npm WARN package.json devahoy-nodejs@0.0.1 No repository field.
npm WARN package.json devahoy-nodejs@0.0.1 No README data
express@4.9.4 node_modules/express
├── utils-merge@1.0.0
├── merge-descriptors@0.0.2
├── cookie@0.1.2
...
├── proxy-addr@1.0.2 (ipaddr.js@0.1.3)
└── on-finished@2.1.0 (ee-first@1.0.5)

ตอนนี้โปรเจ็คของเรา ก็จะมีโฟลเดอร์ node_modules เพิ่มเข้ามา ต่อมาทำการสร้างไฟล์ index.js ขึ้นมา เพื่อใช้เป็นไฟล์หลักที่ใช้เขียน โครงสร้างจะได้ดังนี้

├── index.js
├── node_modules
│   └── express
└── package.json

และไฟล์ package.json ก็จะถูกอัพเดท กลายเป็นแบบนี้

{
  "name": "devahoy-nodejs",
  "version": "0.0.1",
  "description": "Devahoy Node.js with Express 4 Tutorial",
  "main": "index.js",
  "dependencies": {
    "express": "^4.9.4"
  }
}

Step 3 : index.js

ในไฟล์ index.js เพิ่มโค๊ดด้านล่างนี้ลงไป

var app = require('express')()

var port = process.env.PORT || 7777

app.get('/', function (req, res) {
  res.send('<h1>Hello Node.js</h1>')
})

app.get('/index', function (req, res) {
  res.send('<h1>This is index page</h1>')
})

app.listen(port, function () {
  console.log('Starting node.js on port ' + port)
})

เริ่มแรกเราทำการเรียก require('express') เป็นเหมือนการ import โปรเจ็ค express เข้ามาในโปรเจ็คของเรา จากนั้นสั่ง execute แล้วส่งค่าไว้ตัวแปร app จริงๆมีค่าเท่ากับ

var express = require('express')
var app = express()

บรรทัดต่อมา กำหนด port เป็น 7777

ส่วน get(path, callback) จะเป็นในส่วนของ route ของเรา

  • parameter แรก คือ URL ที่เราต้องการ อย่างเช่น / คือหน้า home
  • parameter ตัวสอง คือ callback จะมี request และ response

โดยเมื่อมีการเข้าหน้า home ตัว request ก็จะส่งคำว่า Hello Node.js เช่นเดียวกัน อีกฟังค์ชันใช้ route เป็น /index เมื่อเข้าหน้า /index ก็จะแสดงคำว่า This is index page

ส่วนสุดท้ายคือ app.listen(port) รับค่าเป็นหมายเลข port เพื่อสั่งให้ server ทำการรัน Web Server ด้วย port ที่เรากำหนด ส่วนอีก parameter เป็นออฟชันเสริม จะมีหรือไม่มีก็ได้

สุดท้าย สั่ง start server ด้วยคำสั่ง node ชื่อไฟล์ เช่น

node index.js

Starting node.js on port 7777

ของเปิด บราวเซอร์ด้วย http://localhost:7777 และ http://localhost:7777/index เปรียบเทียบกันดูครับ

Step 4 : Create RESTFul API

เป้าหมายของเรา ไม่ใช่การ render หรือให้ response กลับไปเป็นข้อความ แต่เป้าหมายคือ ต้องการส่งผลลัพธ์กลับไปเป็น JSON ฉะนั้น การส่งผลลัพธ์กลับไป เราจะใช้ฟังค์ชัน res.json() ครับ

ตอนนี้เป้าหมายของผมคือ เมื่อเข้าเว็บ

  • GET localhost:7777/ : ให้แสดงข้อความต้อนรับ
  • GET localhost:7777/user : ให้แสดงรายชื่อ user ทั้งหมดในระบบ
  • GET localhost:7777/user/:id : แสดงชื่อ user นั้นๆ โดย :id คือ เลข id ของ user
  • POST localhost:7777/newuser : เอาไว้สำหรับส่งค่า POST เพื่อเพิ่มข้อมูล user

ทำการสร้างไฟล์ users.js ขึ้นมา ตัวนี้ผมจะเอาไว้สำหรับเป็นข้อมูลของ user ส่วนนี้กำหนดขึ้นมาแบบมั่วๆ เป็น array (ไม่ได้ใช้ฐานข้อมูล)

var users = [
  {
    id: 1,
    username: 'goldroger',
    name: 'Gol D. Roger',
    position: 'Pirate King'
  },
  {
    id: 2,
    username: 'mrzero',
    name: 'Sir Crocodile',
    position: 'Former-Shichibukai'
  },
  {
    id: 3,
    username: 'luffy',
    name: 'Monkey D. Luffy',
    position: 'Captain'
  },
  {
    id: 4,
    username: 'kuzan',
    name: 'Aokiji',
    position: 'Former Marine Admiral'
  },
  {
    id: 5,
    username: 'shanks',
    name: "'Red-Haired' Shanks",
    position: 'The 4 Emperors'
  }
]

exports.findAll = function () {
  return users
}

exports.findById = function (id) {
  for (var i = 0; i < users.length; i++) {
    if (users[i].id == id) return users[i]
  }
}

exports.findAll คือฟังค์ชันสำหรับหา user ทั้งหมดในระบบ ส่วนนี้ผมจะให้ส่งค่า users ทั้งหมด กลับไป ในขณะที่ exports.findById(id) คือฟังค์ชันที่หา user นั้นๆ โดยการระบุ id ก็จะส่งรายละเอียด user นั้นกลับไป ส่วน exports คือความสามารถของ Node.js ที่เราสามารถนำ function หรือโมดูลที่เราเขียนเอง ไปใช้กับไฟล์อื่นได้ครับ

ต่อมาเปิดไฟล์ index.js เพิ่ม require() เพื่อให้ใน index.js สามารถเรียกใช้ฟังค์ชันใน users.js ได้ ใส่เข้าไปบนสุดของไฟล์เลย

var users = require('./users');

จะเห็นว่าเราไม่จำเป็นต้องใส่ นามสกุลของไฟล์ เช่น .js ลงไปด้วย เพียงแค่ระบุชื่อไฟล์และ path ให้ถูก Node.js มันฉลาดพอที่จะรู้ว่าเรา require ไฟล์ไหน

ต่อมา ทำการเพิ่ม route แต่ละอันเข้าไป

app.get('/', function (req, res) {
  res.send('<h1>Hello Node.js</h1>')
})

app.get('/user', function (req, res) {
  res.json(users.findAll())
})

app.get('/user/:id', function (req, res) {
  var id = req.params.id
  res.json(users.findById(id))
})

app.post('/newuser', function (req, res) {
  var json = req.body
  res.send('Add new ' + json.name + ' Completed!')
})

app.listen(port, function () {
  console.log('Starting node.js on port ' + port)
})

โค๊ดด้านบน เมื่อยูเซอร์ เข้าผ่าน localhost/user ก็ให้ทำการเรียกฟังค์ชั่น findAll() จะส่งค่ากลับมาเป็น json จากนั้นใช้ res.json() เพื่อส่งค่าไปแสดงในหน้าเว็บ

เช่นเดียวกัน /user/:id เมื่อระบุ id เป็นหมายเลขไอดีของ user ที่เราต้องการ ก็จะส่ง id เข้าไปในฟังค์ชัน findById(id) โดย id นั้นเราจะอ่านค่าจาก req.params.id

ตัว Route จะเป็น :id แสดงว่า params คือ id ถ้าหาก ตัว Route เป็น :name เราจะอ่านค่า name ด้วย req.params.name

ต่อมา เมื่อเข้า /newuser แต่เป็นแบบ POST ก็จะทำการรับ req.body ซึ่งเราจะส่งค่าเป็น JSON ไป ในส่วนนี้จริงๆ ก็จะนำค่าไปเซฟใน database แต่สำหรับบทความนี้ ผมแค่เอาค่าที่เราส่งไปแบบ POST มาแสดง หน้าเว็บเท่านั้นครับ

ทดสอบ รันผ่านหน้าเว็บดูครับ GET ทั้งหมดทดสอบได้ แต่ว่าเฉพาะ POST ต้องทดสอบผ่าน cURL หรือว่าจะใช้ Chrome Plugin ที่ชื่อว่า Postman ก็ได้ครับ

Step 5 : Test with Postman

ทำการติดตั้ง Postman เพื่อเอาไว้เทส GET/POST ครับ เข้าไปติดตั้งจากลิงค์นี้เลย Postman - REST Client

หน้าตาของ Postman

Postman

สั่ง

node index.js

จากนั้นเปิด Postman แล้วลองใส่ URL ที่ต้องการ กด Send แล้วดูผลลัพธ์ครับ

ต่อมาทดสอบ POST โดยการเลือก POST จากนั้นเลือกข้อมูลแบบ raw ใส่ค่า JSON ที่ต้องการลงไป เช่น

{
  "name": "Roronoa Zoro",
  "position": "Swordman"
}

ลองกด Send ดู...

Test POST Method

Error ซิครับ :D

TypeError: Cannot read property &#39;name&#39; of undefined

เนื่องจากว่า เราไม่สามารถส่งค่า/อ่านค่า body ได้ จึงต้องใช้ body-parser เข้ามาช่วย โดยการ

npm install body-parser --save

จากนั้น ตั้งค่า Body Parser ในไฟล์ index.js ดังนี้ เพื่อให้สามารถ อ่านค่า JSON ได้

var users = require('./users')
var app = require('express')()

var bodyParser = require('body-parser')

var port = process.env.PORT || 7777

// parse application/json
app.use(bodyParser.json())
app.use(
  bodyParser.urlencoded({
    extended: true
  })
)

ทดสอบ start server ใหม่อีกครั้ง

Completed

เรียบร้อย! ได้ผลลัพธ์ตามที่ต้องการ

จะเห็นว่าในบทความนี้ ผมเน้นเรื่องการใช้งาน Node.js และ Express เบื้องต้นซะมากกว่า รู้ว่ามันใช้งาน Route ยังไง มี GET, POST รับส่ง request, response แบบฉบับย่อๆ ไม่ได้ลงรายละเอียดมาก รวมถึงยังไม่ได้พูดถึงฐานข้อมูลเลย ใช้การจำลองข้อมูลแบบเกรียนๆนี้แหละ เซฟเป็น array

สุดท้ายหวังว่าจะอ่านรู้เรื่องกันนะครับ

เนื้อหาเพิ่มเติม

สำหรับเนื้อหาเพิ่มเติม แนะนำให้อ่านจากรายชื่อเว็บด้านล่างเหล่านี้ครับ เอาไปต่อยอดกันเอาเอง

Buy Me A Coffee
Authors
Discord