REST API規範
編寫REST API,實際上就是編寫處理HTTP請求的async函數,不過,REST請求和普通的HTTP請求有幾個特殊的地方:
- REST請求仍然是標準的HTTP請求,但是,除了GET請求外,POST、PUT等請求的body是JSON數據格式,請求的
Content-Type
爲application/json
; - REST響應返回的結果是JSON數據格式,因此,響應的
Content-Type
也是application/json
。
REST規範定義了資源的通用訪問格式,雖然它不是一個強制要求,但遵守該規範可以讓人易於理解。
例如,商品Product就是一種資源。獲取所有Product的URL如下:
GET /api/products
而獲取某個指定的Product,例如,id爲123
的Product,其URL如下:
GET /api/products/123
新建一個Product使用POST請求,JSON數據包含在body中,URL如下:
POST /api/products
更新一個Product使用PUT請求,例如,更新id爲123
的Product,其URL如下:
PUT /api/products/123
刪除一個Product使用DELETE請求,例如,刪除id爲123
的Product,其URL如下:
DELETE /api/products/123
資源還可以按層次組織。例如,獲取某個Product的所有評論,使用:
GET /api/products/123/reviews
當我們只需要獲取部分數據時,可通過參數限制返回的結果集,例如,返回第2頁評論,每頁10項,按時間排序:
GET /api/products/123/reviews?page=2&size=10&sort=time
koa處理REST
既然我們已經使用koa作爲Web框架處理HTTP請求,因此,我們仍然可以在koa中響應並處理REST請求。
我們先創建一個rest-hello
的工程,結構如下:
rest-hello/
|
+- .vscode/
| |
| +- launch.json <-- VSCode 配置文件
|
+- controllers/
| |
| +- api.js <-- REST API
|
+- app.js <-- 使用koa的js
|
+- controller.js <-- 掃描註冊Controller
|
+- package.json <-- 項目描述文件
|
+- node_modules/ <-- npm安裝的所有依賴包
在package.json
中,我們需要如下依賴包:
"dependencies": {
"koa": "2.0.0",
"koa-bodyparser": "3.2.0",
"koa-router": "7.0.0"
}
運行npm install
安裝依賴包。
在app.js
中,我們仍然使用標準的koa組件,並自動掃描加載controllers
目錄下的所有js文件:
const app = new Koa();
const controller = require('./controller');
// parse request body:
app.use(bodyParser());
// add controller:
app.use(controller());
app.listen(3000);
console.log('app started at port 3000...');
注意到app.use(bodyParser());
這個語句,它給koa安裝了一個解析HTTP請求body的處理函數。如果HTTP請求是JSON數據,我們就可以通過ctx.request.body
直接訪問解析後的JavaScript對象。
下面我們編寫api.js
,添加一個GET請求:
// 存儲Product列表,相當於模擬數據庫:
var products = [{
name: 'iPhone',
price: 6999
}, {
name: 'Kindle',
price: 999
}];
module.exports = {
'GET /api/products': async (ctx, next) => {
// 設置Content-Type:
ctx.response.type = 'application/json';
// 設置Response Body:
ctx.response.body = {
products: products
};
}
}
在koa中,我們只需要給ctx.response.body
賦值一個JavaScript對象,koa會自動把該對象序列化爲JSON並輸出到客戶端。
我們在瀏覽器中訪問http://localhost:3000/api/products
,可以得到如下輸出:
{"products":[{"name":"iPhone","price":6999},{"name":"Kindle","price":999}]}
緊接着,我們再添加一個創建Product的API:
module.exports = {
'GET /api/products': async (ctx, next) => {
...
},
'POST /api/products': async (ctx, next) => {
var p = {
name: ctx.request.body.name,
price: ctx.request.body.price
};
products.push(p);
ctx.response.type = 'application/json';
ctx.response.body = p;
}
};
這個POST請求無法在瀏覽器中直接測試。但是我們可以通過curl
命令在命令提示符窗口測試這個API。我們輸入如下命令:
curl -H 'Content-Type: application/json' -X POST -d '{"name":"XBox","price":3999}' http://localhost:3000/api/products
得到的返回內容如下:
{"name":"XBox","price":3999}
我們再在瀏覽器中訪問http://localhost:3000/api/products
,可以得到更新後的輸出如下:
{"products":[{"name":"iPhone","price":6999},{"name":"Kindle","price":999},{"name":"XBox","price":3999}]}
可見,在koa中處理REST請求是非常簡單的。bodyParser()
這個middleware可以解析請求的JSON數據並綁定到ctx.request.body
上,輸出JSON時我們先指定ctx.response.type = 'application/json'
,然後把JavaScript對象賦值給ctx.response.body
就完成了REST請求的處理。