Koa 是下一代的 Node.js 的 Web 框架。由 Express 團隊設計。目的是提供一個更小型、更富有表現力、更可靠的 Web 應用和 API 的開發基礎。
隨着Nodejs新版本正式支持了async和await特性,Koa也當即在2017年2月發佈了V2.0.0版本,咱們稱之爲Koa2。
爲了緊跟潮流,咱們一塊兒來經過一個實際的小項目來學習Koa2。html
既然是爲了完整的學習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
既然要採用REST架構,那麼對REST咱們就須要有一個較全面的瞭解。github
RESTful API與用戶通信的協議,一採用HTTPS協議。(練手項目爲了簡單,就先採用HTTP協議)web
有兩種指明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
儘可能將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就是一個典型的例子。
一個端點就是指向特定資源或資源集合的URL。以構建一個虛擬的動物園的API爲例,咱們有多個動物園,每一個動物園包含有多種的動物,員工,那麼端點能夠設計以下:
https://api.example.org/v1/zoos https://api.example.org/v1/animals https://api.example.org/v1/employees
對具體資源的操做類型,由HTTP動詞表示。
經常使用的HTTP動詞有以下五個:
不經常使用的還有以下的兩個:
仍是以動物園的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: 從指定動物園解僱一個指定的僱員
若是記錄的數據量比較多,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",
對返回的結果按照某個屬性排序以及排序順序。
?sortby=name&order=asc:指定返回結果按照哪一個屬性排序,以及排序順序。 #根據生產者降序和模型升序排列 ?sort=-manufactorer,+model
移動端可以顯示其中一些字段,它們其實不須要一個資源的全部字段,給API消費者一個選擇字段的能力,這會下降網絡流量,提升API可用性。
#僅須要製造商,類型,id和顏色字段 ?fields=manufacturer,model,id,color
服務器向用戶返回的狀態碼和提示信息,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。
當使用不一樣的HTTP動詞向服務器請求時,客戶端須要在返回結果裏面拿到一系列的信息。下面的列表是很是經典的RESTful API定義:
GET /collection: 返回資源對象列表(數組) GET /collection/resource: 返回單個的資源對象 POST /collection: 返回新建立的資源對象 PUT /collection/resource: 返回完整的資源對象 PATCH /collection/resource: 返回完整的資源對象 DELETE /collection/resource: 返回一個空文檔
當一個客戶端建立一個資源時,她們經常不知道新建資源的ID(也許還有其餘的屬性,如建立和修改的時間戳等)。這些屬性將在隨後的請求中返回,而且做爲剛纔POST請求的一個響應結果。
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 來源:簡書 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。