這幾天一直看到 RESTful REST blahblah的資料,
但其實一直沒有很明白RESTful是什麼意思,因此決定透過實做來了解什麼是RESTful了
首先,要來介紹什麼是 REST
REST (Representational State Transfer) 中文翻譯叫做「具象狀態傳輸」,
是一種網路架構風格,目的是便於不同軟體/程序在網絡(例如網際網路)中互相傳遞信息。
-- Wikipedia
符合REST風格的Web API就被稱為 RESTful API
以 API 而言,假設我們正在撰寫一組待辦事項的 API,
- 可能會有以下方式來作為 API 的 interface:
獲取使用者資料
/getAllUsers
獲取使用者1號資料/getUser/1
新增使用者資料/createUser
更新使用者資料/updateUser/1
刪除使用者資料/deleteUser/1
- 若是以 REST 風格來開發 RESTful API 的話:
獲取使用者資料
/GET /users
獲取使用者1號資料/GET /user/1
新增使用者資料/POST /user
更新使用者資料/PUT /user/1
刪除使用者資料/DELETE /user/1
--什麼是 REST/RESTful
從這邊就可以看出REST風格開發的充分利用了前面說過的HTTP method
而設計一個好的RESTful API有以下需要先了解
HTTP動詞(只擷取常見的)
GET
: 讀取資源PUT
: 替換資源DELETE
: 刪除資源POST
: 新增資源;也作為萬用動詞,處理其它要求URI名詞
URI由prefix + API endpoint組成,而Prefix的部份可有可無 (/api 可以省略)。
HTTP回傳狀態碼
2xx
: 成功3xx
: 重新導向4xx
: 用戶端錯誤(用戶端不應retry原始請求)5xx
: 伺服器錯誤(用戶端可合理retry)HTTP Header
HTTP Body: JSON或XML格式
RESTful API是一種設計風格,使API設計具有整體一致性,易於維護、擴展,且充份利用HTTP協定的特點。
-- 簡明RESTful API設計要點
有個大略的了解後就開始來設計RESTful API吧!
這次要來作一個簡單的 ToDo List (底下的事項稱作task)
POST
): /tasks
GET
): /tasks/:taskId
DELETE
): /tasks/:taskId
GET
): /tasks
PUT
): /tasks/:taskId
備註
因為這次的練習牽涉到了後端,因此採用 Mongoose 來實作資料庫。
Mongoos是一套給 Node.js 用的 MongoDB ODM 資料庫
上述都做好後就能開始做Todo List了!
打開你的終端機,在你想要建立todoListApi資料夾的地方輸入 mkdir todoListApi
前往該資料夾 cd todoListApi
如上圖,我自己是建立在桌面
輸入npm init
,之後會要求你輸入名字、版本等訊息,
只有名字是必須輸入的,其他均可以略過,我輸入的名字是todolist
我們可以透過 npm init
來生成 package.json來定義相關套件,更多資訊可以點此處。
輸入 touch server.js
在這個資料夾內建立 server.js
輸入 mkdir api
建立一個api資料夾,並輸入 mkdir api/controllers api/models api/routes
api在底下建立三個不同的資料夾(models, routes, controllers)
輸入 touch api/controllers/todoListController.js api/models/todoListModel.js api/routes/todoListRoutes.js
在三個資料夾底下分別建立對應的js檔(還是空的)
所以現在你的資料夾看起來像是這樣
輸入 npm install --save-dev nodemon
安裝nodemon協助程式開發
輸入 npm install express --save
輸入 npm install mongoose --save
安裝Mongoose
打開package.json在script的部分加上 "start": "nodemon server.js"
做完以上步驟後就能開始打code了!
先打開 server.js
貼上以下的程式碼
var express = require('express'),
app = express(),
port = process.env.PORT || 300;
app.listen(port);
console.log('todo list RESTful API server started on: ' + port);
在終端機輸入 npm run start
就會發現server開始運作
打開 todoListModel.js
貼上以下的程式碼
'use strict'; //未必要寫
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
//建立一個model表現collection的樣子(name, Created_date, status)並規定它的格式
//collection包含name:任務名字 Created_date:建立日期 status:目前狀態('pending', 'ongoing', 'completed')
var TaskSchema = new Schema({
name: {
type: String,
Required: 'Kindly enter the name of the task'
},
Created_date: {
type: Date,
default: Date.now
},
status: {
type: [{
type: String,
enum: ['pending', 'ongoing', 'completed']
}],
default: ['pending']
}
});
module.exports = mongoose.model('Tasks', TaskSchema);
打開 todoListRoutes.js
貼上以下程式碼
'use strict';
module.exports = function(app) {
var todoList = require('../controllers/todoListController');
// todoList Routes
app.route('/tasks')
.get(todoList.list_all_tasks)
.post(todoList.create_a_task);
app.route('/tasks/:taskId')
.get(todoList.read_a_task)
.put(todoList.update_a_task)
.delete(todoList.delete_a_task);
};
routing決定了server會如何回應HTML的請求(request)
這裡有兩種route(/tasks
和 /tasks/:taskId
)分別對應到不同的請求(GET/POST
和 GET/PUT/DELETE
)以及回應
打開 todoListController.js
貼上以下的程式碼
'use strict';
var mongoose = require('mongoose'),
Task = mongoose.model('Tasks'); //一開始建立的Tasks schema
//針對不同request的回應(json格式)
exports.list_all_tasks = function(req, res) {
Task.find({}, function(err, task) {
if (err)
res.send(err);
res.json(task);
});
};
//CRUD
exports.create_a_task = function(req, res) {
var new_task = new Task(req.body);
new_task.save(function(err, task) {
if (err)
res.send(err);
res.json(task);
});
};
exports.read_a_task = function(req, res) {
Task.findById(req.params.taskId, function(err, task) {
if (err)
res.send(err);
res.json(task);
});
};
exports.update_a_task = function(req, res) {
Task.findOneAndUpdate(req.params.taskId, req.body, { new: true }, function(err, task) {
if (err)
res.send(err);
res.json(task);
});
};
exports.delete_a_task = function(req, res) {
Task.remove({
_id: req.params.taskId
}, function(err, task) {
if (err)
res.send(err);
res.json({ message: 'Task successfully deleted' });
});
};
修改 server.js
貼上以下的程式碼
var express = require('express'),
app = express(),
port = process.env.PORT || 3000,
mongoose = require('mongoose'),
Task = require('./api/models/todoListModel'),
bodyParser = require('body-parser');
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost/Tododb');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var routes = require('./api/routes/todoListRoutes');
routes(app);
app.listen(port);
console.log('todo list RESTful API server started on: ' + port);
透過URL連接MongoDB (Tododb
)到server上
載入寫好的Schema Tasks
安裝、使用 bodyParser
解析回傳的json資料
$ npm install --save body-parser
把之前寫好的routes (todoListRoutes
)掛上server的route上
啟動mongoDB (可能要在mongoDB安裝處才可使用此指令)
$ mongod
假使你的mongoDB需要重新啟動,輸入 rs
就能重新啟動了
server成功畫面如上圖,可以開始測試功能了
開啟你的Postman 輸入 http://localhost:3000/tasks
得到的值應該要是 [] ,因為還沒有任何task被建立
動作改為 POST
,在key的部分寫上name,value的部分寫上task名稱後送出就能新增task了
重複做多次後就如下圖,使用GET
得到的就不再是[]了
要刪除task的話,把動作改為 DELETE
,網址改為 http://localhost:3000/tasks/taskid
就能夠成功刪除
用 GET
,網址一樣用 http://localhost:3000/tasks/taskid ,則是能得到單筆資料情形
以上就是簡單的restful api練習!
因為感冒 + 期中考 + 作業纏身,這篇文打了好久好久好久......
我是個nodejs初學者,在學習這篇的mongoose應用的時候遇到一點問題,也順利解決了,所以留個註記,給跟我遇到一樣問題的人看,並解決問題。
文章從
輸入
npm install mongoose --save
安裝Mongoose
打開package.json在script的部分加上"start": "nodemon server.js"
開始出現一個mongoose後續設定的斷層,導致最後執行node server.js
的時候會跳Error
Tododb
這是用來存放資料的mongodb/bin
並執行 mongod --dbpath=D:\mongodb\Tododbnode server.js
就可以順利跑起來了我遇到的問題是mongodb一開始沒有啟動與設定,所以才會在最後卡關,不過啟動mongodb之後,所有問題就迎刃而解了,題外話... 除了用Brackets寫nodejs還有更好的選擇嗎?用Eclipse寫程式寫久了,都會忘記去注意一些打錯字的問題,有時候遇到Bug找很久才發現是字母打錯..
我自己是用sublime去寫
可能是因為我是MacOS系統所以沒有出現那個問題吧QQ
推VS CODE 很多插件可以裝還蠻不錯的