使用REST API, 我們能夠通過HTTP請求來對MongoDB進行CRUD操作. REST API對於我們的應用來說就是一個無狀態的接口, 對於MEAN技術棧來講, REST API的地位是創建一個暴露一個操作數據庫的無狀態接口, 供其他應用操作數據庫的數據.
設計REST API的請求處理部分
REST API功能
通常, 我們希望藉助REST API完成以下操作
- 創建一個新記錄
- 讀取一個list的記錄
- 讀取指定的記錄
- 更新指定記錄
- 刪除指定記錄
假如我們現在要創建的是地址記錄, 假定我們要使用的URL路徑是/locations
, 那麼各個操作對應到URL
路徑之後如下表所示
動作 | URL路徑 | 路徑參數 | 例子 |
---|---|---|---|
創建一個新記錄 | /locations | http://example/api/locations | |
讀取一個list的記錄 | /locations | http://example/api/locations | |
讀取指定的記錄 | /locations | locationId | http://example/api/locations/123 |
更新指定記錄 | /locations | locationId | http://example/api/locations/123 |
刪除指定記錄 | /locations | locationId | http://example/api/locations/123 |
通過上表可以看出, 多個不同的動作可能對應的是相同的URL路徑, 那麼如何進行動作的區分呢? 答案是通過HTTP請求類型來判斷.
HTTP請求類型
通常, REST API使用到四種HTTP請求, 它們的用途和相應如下所示
HTTP請求類型 | 用途 | 響應 |
---|---|---|
POST | 創建新記錄 | 數據庫中插入新記錄 |
GET | 讀取記錄 | 從數據庫返回指定記錄 |
PUT | 更新記錄 | 更新數據庫中的指定記錄 |
DELETE | 刪除記錄 | 數據庫中指定記錄被刪除 |
結合HTTP請求類型和URL路徑確定唯一的操作
動作 | HTTP請求類型 | URL路徑 | 路徑參數 | 例子 |
---|---|---|---|---|
創建一個新記錄 | POST | /locations | http://example/api/locations | |
讀取一個list的記錄 | GET | /locations | http://example/api/locations | |
讀取指定的記錄 | GET | /locations | locationId | http://example/api/locations/123 |
更新指定記錄 | PUT | /locations | locationId | http://example/api/locations/123 |
刪除指定記錄 | DELETE | /locations | locationId | http://example/api/locations/123 |
使用REST API操作子文檔
以上介紹都是REST API操作父文檔, 如果想操作子文檔, 首先需要獲取到父文檔, 也就是如上表中的http://example/api/locations/123這樣的路徑, 現在假定每個location
文檔中還內嵌了名爲reviews
的子文檔, 那麼它所對應的操作如下
動作 | HTTP請求類型 | URL路徑 | 路徑參數 | 例子 |
---|---|---|---|---|
創建一個新記錄 | POST | /locations/locationId/reviews | locationId | http://example/api/locations/123/reviews |
讀取指定的記錄 | GET | /locations/locationId/reviews | locationId reviewId |
http://example/api/locations/123/reviews/abc |
更新指定記錄 | PUT | /locations/locationId/reviews | locationId reviewId |
http://example/api/locations/123/reviews/abc |
刪除指定記錄 | DELETE | /locations/locationId/reviews | locationId reviewId |
http://example/api/locations/123/reviews/abc |
注意, 子文檔的操作並沒有一個讀取list的操作, 因爲這個操作可以通過對父文檔操作進行實現.
設計REST API響應(Response)和狀態碼
REST API的另一部分就是響應的設計, 響應一般來說包含兩個部分:
- 返回數據
- HTTP狀態碼
對於返回數據, 通常是JSON或者XML類型的, 這裏我們選擇JSON類型, 因爲它比XML數據更加緊湊, 並且天然適應MEAN技術棧. 對於每個請求, 返回數據都應該有三種類型:
- 包含正確返回的被請求數據的JSON對象
- 包含錯誤信息的JSON對象
- null響應
常用的HTTP狀態碼
HTTP狀態碼通常是用來和響應一同返回的, 用於表明HTTP請求的執行情況.
常用的HTTP狀態碼共有10種
狀態碼 | 名稱 | 適用場景 |
---|---|---|
200 | OK | GET 或者PUT 請求成功 |
201 | Created | POST 請求成功 |
204 | No content | DELETE 請求成功 |
400 | Bad request | GET , PUT 或者POST 請求由於內容不符合標準而失敗 |
401 | Unauthorized | 身份驗證未通過 |
403 | Forbidden | 不允許的請求 |
404 | Not found | 請求的URL沒有資源或者參數錯誤 |
405 | Method not allowed | 指定的URL不允許此種請求類型 |
409 | Conflict | POST 失敗, 試圖插入重複數據 |
500 | Internal server error | 服務器或數據庫故障 |
在Express中建立響應API
使REST API不與應用的其他處理邏輯混雜, 所以這裏我們單獨對其進行管理.
首先, 在應用的根目錄新建一個app_api
目錄, 這個目錄將會包含routes
, controllers
, models
(注意並沒有views
)
創建REST API路由
首先創建根路由, 也就是index.js
, 並將其加載到app.js
中,
var index = require('./app_server/routes/index');
// 以下是新增的路由
var apiIndex = require('./app_api/routes/index');
app.use('/', index);
// 以下是新增的路由
app.use('/api', apiIndex);
TODO 未完待續