RESTful API 實踐

什麼是 REST?

REST 即表述性狀態傳遞(英文:Representational State Transfer,簡稱REST)是Roy Fielding博士在2000年他的博士論文中提出來的一種軟件架構風格(http://www.ics.uci.edu/~field...)。它是一種針對網絡應用的設計和開發方式,能夠下降開發的複雜性,提升系統的可伸縮性。html

六個約束:

  • 統一接口(Uniform Interface)git

  • 無狀態(Stateless)github

  • 緩存(Cacheable)api

  • 客戶-服務器(Client-Server)xcode

  • 分層系統(Layered System)緩存

  • 按需代碼(Code on Demand)服務器

統一接口(Uniform Interface)

使REST 架構風格區別於其餘基於網絡的架構風格的核心特徵是,它強調組件之間要有一個統一的接口。經過在組件接口上應用通用性的軟件工程原則,總體的系統架構獲得了簡化,交互的可見性也獲得了改善。實現與它們所提供的服務是解耦的,這促進了獨立的可進化性。然而,付出的代價是,統一接口下降了效率,由於信息都使用標準化的形式來轉移,而不能使用特定於應用的需求的形式。REST 接口被設計爲能夠高效地轉移大粒度的超媒體數據,並針對Web的常見狀況作了優化,可是這也致使了該接口對於其餘形式的架構交互並非最優的。restful

無狀態(Stateless)

通訊必須在本質上是無狀態的,所以從客戶到服務器的每一個請求都必須包含理解該請求所必需的全部信息,不能利用任何存儲在服務器上的上下文,會話狀態所以要所有保存在客戶端。網絡

緩存(Cacheable)

爲了改善網絡的效率。緩存約束要求一個請求的響應中的數據被隱式地或顯式地標記爲可緩存的或不可緩存的。若是響應是可緩存的,那麼客戶端緩存就能夠爲之後的相同請求重用這個響應的數據。架構

客戶-服務器(Client-Server)

經過分離用戶接口和數據存儲這兩個關注點,咱們改善了用戶接口跨多個平臺的可移植性;同時經過簡化服務器組件,改善了系統的可伸縮性。然而,對於 Web來講,最重要的是這種關注點的分離容許組件獨立地進化,從而支持多個組織領域的Internet規模的需求。

分層系統(Layered System)

分層系統風格經過限制組件的行爲(即,每一個組件只能「看到」與其交互的緊鄰層),將架構分解爲若干等級的層。經過將組件對系統的知識限制在單一層內,爲整個系統的複雜性設置了邊界,而且提升了底層獨立性。咱們可以使用層來封裝遺留的服務,使新的服務免受遺留客戶端的影響,經過將不經常使用的功能轉移到一個共享的中間組件中,從而簡化組件的實現。中間組件還可以經過支持跨多個網絡和處理器的負載均衡,來改善系統的可伸縮性。

按需代碼(Code on Demand)

經過減小必須被預先實現的功能的數目,簡化了客戶端的開發。容許在部署以後下載功能代碼也改善了系統的可擴展性。然而,這也下降了可見性,所以它只是 REST 的一個可選的約束。

HTTP 動做

GET

HTTP GET 用於檢索(讀取)資源。正確的狀況返回JSON200 HTTP響應碼,在錯誤的狀況下他們一般返回404(NOT FOUND)400(BAD REQUEST)

示例

GET http://www.example.com/custom...
GET http://www.example.com/custom...
GET http://www.example.com/bucket...

經過GET它應該永遠不會修改服務器上的任何資源。

POST

HTTP POST 一般用於建立資源。正確的狀況返回201 HTTP響應碼及Location header(資源 URI)。

示例

POST http://www.example.com/customers
POST http://www.example.com/custom...

PUT

HTTP PUT 一般用於更新資源。將請求正文內容替換已知資源的原始數據。

示例

PUT http://www.example.com/custom...
PUT http://www.example.com/custom...

DELETE

HTTP DELETE 用於刪除由URI標識的資源。成功刪除返回200 HTTP及響應正文或沒有正文響應204 HTTP(NO CONTENT)

示例

DELETE http://www.example.com/custom...
DELETE http://www.example.com/custom...
DELETE http://www.example.com/bucket...

下表是 URI 結合 HTTP METHOD 建議的返回值

HTTP Verb(Method) /customers /customers/{id}
GET 200 (OK)。客戶列表,數據量大可以使用分頁排序篩選 200 (OK)。單個客戶。404 (Not Found) ID客戶不存在,400 (BAD REQUEST) ID不合法
POST 201 (Created),'Location' header 爲 /customers/{id} 包含新的資源ID 404 (Not Found)
PUT 404 (Not Found) 200 (OK)或者204 (No Content)。404 (Not Found) ID客戶不存在,400 (BAD REQUEST) ID不合法
DELETE 404 (Not Found) 200 (OK)或者204 (No Content)。404 (Not Found) ID客戶不存在,400 (BAD REQUEST) ID不合法

資源命名

一切在工藝軟件開發的命名是成功的關鍵。

除了適當的應用 HTTP Verb(Method),資源命名能夠說是最受爭議和最重要的概念。當資源被命名好時,API 是直觀和易於使用的。作得太差,一樣的 API 能感受太表面化和難以使用和理解。下面是一些提示,讓你去當建立資源 URI 爲您新的 API。

資源 URI 應使用名詞而不是動詞命名。一個 RESTful URI 應該指一種資源,而不是採起行動。名詞具備屬性而動詞沒有。

服務套件中每一個資源至少有一個 URI 標識它。URI 應遵循一種可預見,分層結構,以增長可理解性,從而提升可用性。

在一個訂單系統與客戶、訂單、行項目的資源設計:

建立一個新的客戶
POST http://www.example.com/customers

讀取客戶 ID 爲 33245
GET http://www.example.com/custom...
相同的 URI 將用於更新(PUT)與刪除(DELETE)客戶

這裏爲產品設計的 URI:
POST http://www.example.com/products
建立一個新的產品

GET|PUT|DELETE http://www.example.com/produc...
讀取、更新、刪除 ID 爲 66432 的產品爲

如今變得頗有趣,咱們如何爲客戶建立新的訂單?
一種選擇是
POST http://www.example.com/orders
毫無疑問它是能夠工做的,但它卻在客戶的上下文以外

下面的 URI 更清晰
POST http://www.example.com/custom...
如今咱們知道這個訂單是爲客戶 33245 建立的

獲取 33245 客戶訂單使用以下 URI
GET http://www.example.com/custom...
如今,咱們繼續來看分層的 URI 設計。以下:
POST http://www.example.com/custom...
這會將行項目添加到訂單 #8769(這是客戶 #33245),獲取該 URI 資源會返回訂單下全部的行項目,若是行項目毫無心義或者在客戶的上下文之外的地方能感受到咱們會提供這樣一個 URI
POST www.example.com/orders/8769/lineitems

看看一些普遍使用的 API 來獲得資源命名竅門和利用你的隊友來完善您的 API 資源。

Response Body

簡單響應

示例

{
   "url":"https://api.github.com/gists/20c98223d9b59e1d48e5",
   "id":"1",
   "description":"description of gist",
   "public":true,
   "user":{
       "login":"octocat",
       "id":1,
       "avatar_url":"https://github.com/images/error/octocat_happy.gif",
       "gravatar_id":"somehexcode",
       "url":"https://api.github.com/users/octocat"
   },
   "comments":0,
   "comments_url":"https://api.github.com/gists/19d18b30e8af75090307/comments/",
   "html_url":"https://gist.github.com/1",
   "git_pull_url":"git://gist.github.com/1.git",
   "git_push_url":"git@gist.github.com:1.git",
   "created_at":"2010-04-14T02:15:15Z"
}

分頁響應

  • total_count 總記錄數

  • items 數據項

示例

{
   "total_count":40,
   "items":[
       {
           "id":3081286,
           "name":"Tetris",
           "full_name":"dtrupenn/Tetris",
           "owner":{
               "login":"dtrupenn",
               "id":872147,
               "type":"User"
           },
           "private":false,
           "html_url":"https://github.com/dtrupenn/Tetris",
           "description":"A C implementation of Tetris using Pennsim through LC4",
           "fork":false,
           "url":"https://api.github.com/repos/dtrupenn/Tetris",
           "created_at":"2012-01-01T00:31:50Z",
           "updated_at":"2013-01-05T17:58:47Z",
           "pushed_at":"2012-01-01T00:37:02Z"
       }
   ]
}

錯誤響應

  • code 錯誤碼

  • message 錯誤信息

示例

{
   "code": 12345,
   "message": "錯誤描述"
}

參考資源

http://www.restapitutorial.com/
https://www.oschina.net/trans...

相關文章
相關標籤/搜索