Koa2實戰練手(一)------ 學習RESTful API

Koa 是下一代的 Node.js 的 Web 框架。由 Express 團隊設計。目的是提供一個更小型、更富有表現力、更可靠的 Web 應用和 API 的開發基礎。
隨着Nodejs新版本正式支持了async和await特性,Koa也當即在2017年2月發佈了V2.0.0版本,咱們稱之爲Koa2。
爲了緊跟潮流,咱們一塊兒來經過一個實際的小項目來學習Koa2。html

1、項目設計

既然是爲了完整的學習Koa2,確定不能只作一個「Hello world!」,咱們能夠作一個「Hello Koa2!」。呵呵,言歸正傳。什麼項目既足夠小,又能完整的學習一個web框架了? 固然是框架最流行的"Hello world"項目:TODO應用。node

本次計劃開發的TODO List應用使用先後端分離的設計,採用REST(Representational State Transfer)架構。REST是Roy Thomas Fielding在2000年的論文Architectural Styles and
the Design of Network-based Software Architectures
中提出的。git

2、學習REST

既然要採用REST架構,那麼對REST咱們就須要有一個較全面的瞭解。github

2.1 REST設計原則

  1. 每一個URI表示一種資源(resource)
  2. URI應該使用名稱而不是動詞
  3. 使用複數名詞
  4. GET方法不能改變狀態
  5. HTTP協議中四種方法對應四種基本的操做:
    • GET: 獲取資源(select)
    • POST:新建資源(create)
    • PUT:更新資源(update)
    • DELETE:刪除資源(delete)
  6. 其餘方法
    • HEAD:獲取資源的元數據(meta data),例如數據的hash值或則資源的最後更新時間
    • OPTIONS:返回當前資源容許客戶作哪些操做;
  7. 使用子資源表示關係
  8.  

2.二、協議

RESTful API與用戶通信的協議,一採用HTTPS協議。(練手項目爲了簡單,就先採用HTTP協議)web

2.三、版本(Versioning)

有兩種指明API版本的方法:express

A. 版本號放到HTTPS請求的頭信息的Accept字段中:json

Accept: vnd.example-com.foo+json; version=1.0
Accept: vnd.example-com.foo+json; version=1.1
Accept: vnd.example-com.foo+json; version=2.0

#github採用以下的形式指明版本號
Accept: application/vnd.github.v3+json

B 將版本號放到URL中後端

https://api.example.com/v1/

#豆瓣API
https://api.douban.com/v2/book/isbn/:name

2.四、API根地址

儘可能將API部署在專用域名下。例如github和豆瓣的API就是部署在專用域名下。此種方式適用於應用比較複雜和龐大,在規模化時靈活性比較好。api

https://api.douban.com/v2/book/isbn/:name
https://api.github.com/
https://api.example.com

在簡單的狀況下,也能夠將API部署到主域名之下。這樣能夠採用相同的框架同時支持站點和API。數組

https://example.org/api/

同時API的根返回API的相關說明是一個較好的實踐。github的根API就是一個典型的例子。

2.5 端點(Root Endpoint)

一個端點就是指向特定資源或資源集合的URL。以構建一個虛擬的動物園的API爲例,咱們有多個動物園,每一個動物園包含有多種的動物,員工,那麼端點能夠設計以下:

https://api.example.org/v1/zoos
https://api.example.org/v1/animals
https://api.example.org/v1/employees

2.6 HTTP動詞

對具體資源的操做類型,由HTTP動詞表示。

經常使用的HTTP動詞有以下五個:

  • GET(SELECT): 獲取資源
  • POST(CREATE):新建資源
  • PUT(UPDATE):更新資源(客戶端提供改變後的完整資源)
  • PATCH(UPDATE):在服務器更新資源(客戶端只提供改變的屬性)
  • DELETE(DELETE):刪除資源

不經常使用的還有以下的兩個:

  • HEAD:獲取資源的元數據(meta data),例如數據的hash值或則資源的最後更新時間
  • OPTIONS:返回當前資源容許客戶作哪些操做;

仍是以動物園的API爲例。對於每個端點,能夠列出全部可行的HTTP動詞和端點的組合。

GET /zoos: 列出全部動物
POST /zoos: 新建一個動物園
GET /zoos/ZID: 獲取指定動物園的信息
PUT /zoos/ZID: 更新指定的動物園(提供該動物園的完整信息)
PATCH /zoos/ZID: 更新指定的動物園(提供該動物園的部分信息)
DELETE /zoos/ZID: 刪除指定的動物園
GET /zoos/ZID/animals: 獲取指定動物園的全部動物
DELETE /zoos/ZID/animals/AID: 刪除指定動物園的指定動物
GET /zoos/ZID/employees: 列出指定動物園的全部僱員
POST /zoos/ZID/employees: 在指定動物園僱傭一個新僱員
DELETE /zoos/ZID/employees/EID: 從指定動物園解僱一個指定的僱員

2.7 過濾信息和分頁(Filtering & Paging)

若是記錄的數據量比較多,API就應該提供參數,對返回的結果進行過濾。經常使用的參數有以下一些:

#limit和offset就能實現分頁
?limit=10:指定返回記錄的數量
?offset=10:指定返回記錄的開始位置。
?page=2&per_page=100:指定第幾頁,以及每頁的記錄數。


#爲了將總數發給客戶端,使用訂製的HTTP頭: X-Total-Count.
#連接到下一頁或上一頁能夠在HTTP頭的link規定,遵循Link規定:

Link: <https://blog.mwaysolutions.com/sample/api/v1/cars?offset=15&limit=5>; rel="next",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=50&limit=3>; rel="last",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=0&limit=5>; rel="first",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=5&limit=5>; rel="prev",

2.8 排序(Sorting)

對返回的結果按照某個屬性排序以及排序順序。

?sortby=name&order=asc:指定返回結果按照哪一個屬性排序,以及排序順序。

#根據生產者降序和模型升序排列
?sort=-manufactorer,+model

2.9 字段選擇(Field selection)

移動端可以顯示其中一些字段,它們其實不須要一個資源的全部字段,給API消費者一個選擇字段的能力,這會下降網絡流量,提升API可用性。

#僅須要製造商,類型,id和顏色字段
?fields=manufacturer,model,id,color

2.10 狀態碼(Status Codes)

服務器向用戶返回的狀態碼和提示信息,HTTP 1.1中常見的有如下一些(方括號中是該狀態碼對應的HTTP動詞)。

200 OK - [GET]:服務器成功返回用戶請求的數據,該操做是冪等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數據成功。
202 Accepted - [*]:表示一個請求已經進入後臺排隊(異步任務)
204 NO CONTENT - [DELETE]:客戶端要求服務器刪除一個資源,服務器刪除成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發出的請求有錯誤,服務器沒有進行新建或修改數據的操做,該操做是冪等的。
401 Unauthorized - [*]:表示用戶沒有權限(令牌、用戶名、密碼錯誤)。
403 Forbidden - [*] 表示用戶獲得受權(與401錯誤相對),可是訪問是被禁止的。
404 NOT FOUND - [*]:用戶發出的請求針對的是不存在的記錄,服務器沒有進行操做,該操做是冪等的。
406 Not Acceptable - [GET]:用戶請求的格式不可得(好比用戶請求JSON格式,可是隻有XML格式)。
410 Gone -[GET]:用戶請求的資源被永久刪除,且不會再獲得的。
422 Unprocesable entity - [POST/PUT/PATCH] 當建立一個對象時,發生一個驗證錯誤。
500 INTERNAL SERVER ERROR - [*]:服務器發生錯誤,用戶將沒法判斷髮出的請求是否成功。

狀態碼範圍(Status Code Ranges)

1xx  保留給底層HTTP功能使用
2xx  保留給成功消息使用
3xx  保留給重定向使用,通常API不會使用此類狀態
4xx  保留給客戶端錯誤使用。例如,客戶端提供了一些錯誤的數據或請求了不存在的內容。這些請求應該是冪等的,不會改變任何服務器的狀態。
5xx  保留給服務器端錯誤用的。這些錯誤經常是從底層的函數拋出來的,而且開發人員也一般無法處理。發送這類狀態碼的目的是確保客戶端能獲得一些響應。收到5xx響應後,客戶端沒辦法知道服務器端的狀態,因此這類狀態碼是要儘量的避免。

完整狀態碼列表能夠參考RFC2616

2.11 返回結果

當使用不一樣的HTTP動詞向服務器請求時,客戶端須要在返回結果裏面拿到一系列的信息。下面的列表是很是經典的RESTful API定義:

GET /collection: 返回資源對象列表(數組)
GET /collection/resource: 返回單個的資源對象
POST /collection: 返回新建立的資源對象
PUT /collection/resource: 返回完整的資源對象
PATCH /collection/resource: 返回完整的資源對象
DELETE /collection/resource: 返回一個空文檔

當一個客戶端建立一個資源時,她們經常不知道新建資源的ID(也許還有其餘的屬性,如建立和修改的時間戳等)。這些屬性將在隨後的請求中返回,而且做爲剛纔POST請求的一個響應結果。

2.12 Hypermedia API

RESTful API最好作到Hypermedia,即返回結果中提供連接,連向其餘API方法,使得用戶不查文檔,也知道下一步應該作什麼。
好比,當用戶向api.example.com的根目錄發出請求,會獲得這樣一個文檔。

{
    "link": {
        "rel": "collection https://www.example.com/zoos",
        "href": "https://api.example.com/zoos",
        "title": "List of zoos",
        "type": "application/vnd.yourformat+json"
    }
}

上面代碼表示,文檔中有一個link屬性,用戶讀取這個屬性就知道下一步該調用什麼API了。rel表示這個API與當前網址的關係(collection關係,並給出該collection的網址),href表示API的路徑,title表示API的標題,type表示返回類型。
Hypermedia API的設計被稱爲HATEOAS。Github的API就是這種設計,訪問api.github.com會獲得一個全部可用API的網址列表。

{
  "current_user_url": "https://api.github.com/user",
  "authorizations_url": "https://api.github.com/authorizations",
  // ...
}

從上面能夠看到,若是想獲取當前用戶的信息,應該去訪問api.github.com/user,而後就獲得了下面結果。

{
    "message": "Requires authentication",
    "documentation_url": "https://developer.github.com/v3"
}

上面代碼表示,服務器給出了提示信息,以及文檔的網址。

項目已經發布到github: koa-todo

參考文章:
阮一峯 RESTful API 設計指南

做者:Q_幽蘭_Q 連接:https://www.jianshu.com/p/c37a13506753 來源:簡書 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。

相關文章
相關標籤/搜索