這篇博文講先後端交互的Restful API設計考慮。API必定是基於HTTP協議並儘可能靠攏Restful規範設計的。若是不瞭解HTTP協議,能夠參考個人博文HTTP必知必會。關於Restful是怎麼回事,能夠考慮先參考阮一峯的博文理解RESTful架構;嫌麻煩的能夠略過直接閱讀個人這篇博文。html
所謂資源,是一種對事物的抽象。一我的、一頭牛、一張電影票、一句話、一個想法均可以抽象爲資源。json
URL是資源的定位,是一種映射關係,即一個URL必定定位到最多不超過一個的資源。根據URL佈局的特色,分爲三種類型的資源:後端
集合資源api
對於形如/users
的資源稱爲集合資源,它表示一羣用戶。數組
個體資源服務器
對於形如/users/u123
的資源稱爲個體資源,它表示一個用戶,它是經過一個惟一標識的id(即u123)來肯定這個用戶。restful
子集合資源架構
對於形如/users/u123/messages
的資源稱爲子集合資源,它表示某個用戶的一羣消息,這個用戶是經過惟一標識的id(即u123)來肯定的。app
資源的id對於同種類型的資源來講必定是惟一的。也就是說,肯定一個個體資源只須要經過下面的方式便可佈局
/messages/m123
而沒必要
/users/u123/messages/m123
資源自己是一種抽象,它必需要轉化爲一種機器可讀的形式才能進行傳輸和處理。表述方式的例子如表單形式、XML、JSON等。能夠經過HTTP頭Content-Type來指定資源的表述形式,常見的例子:
這裏的設計中只考慮一種表述形式,即JSON。但願這一點不會給API的調用帶來困擾。
對於的基本的增刪改查操做,除了定位到資源之外,只須要附加一個HTTP方法夠了。根據Restful規範,方法對於集合的意義通常是:
這些方法適用於不一樣的URL類型,總結以下:
GET+(子)集合資源
POST+(子)集合資源
GET+個體資源
PUT/PATCH+個體資源
DELETE+個體資源
當對資源的操做跳出了基本的增刪改查範疇,就在資源的URL表示以後增長動做的名稱便可。這能夠經過兩個典型的例子來闡述。
這個屬於對集合資源進行的操做。其接口表示可設定爲:
只需在集合資源的URL表示(即/users)以後附加動做名(即/login)便可。在這種狀況下,POST是典型方法。
這是一對接口,其中一個是對一本書進行標星操做,另一個是對其進行取消標星操做。這兩個接口都屬於對個體資源的操做。其接口表示可分別設定爲:
首先,須要在個體資源的URL表示(即/books/b123)以後附加動做名(即/star)。其次,這裏用到對立的兩個方法POST和DELETE。
一個查詢接口會返回一個資源數組,但有時咱們須要知道知足某個查詢條件的資源總數。這個在集合資源的URL以後附加動做count便可。例如:
注意,這時分頁控制無效。
在參數設計裏,一個基本的設計原則是要保證簡潔,避免嵌套過深。參數的格式能夠根據實際狀況限定爲幾種或不限格式。不過,至少保證表單格式和JSON格式這兩種格式的支持。其中JSON格式支持任意的嵌套;表單格式對嵌套的支持不理想。
參數分爲通常參數和控制參數。從形式上看,控制參數如下劃線開頭。這麼設計是爲了與通常參數進行區分。通常參數例如name、age等,控制參數例如_sort等。
這裏的篩選只支持徹底匹配,適用於GET集合資源的接口。篩選的方式是簡單直接的,直接是字段名=值
的形式便可。例以下面的接口返回年齡爲18的全部男性用戶:
GET /users?age=18&gender=male
排序參數_sort是逗號分隔的字段列表,以+/-表示升/降序。
分頁參數_range的構建也是直接的,如下劃線分隔它的起始和結束資源的序號。資源計數從1開始,這點要尤爲注意。
說清楚內嵌的用法,先定義一個資源Book:
{ id: 'b123', title: 'xxx', author: { id: 'u123', name: 'yyy' } }
經過GET接口獲取的資源表述中,對於內嵌的資源默認只會返回其id,而不會返回其完整表述。例如調用GET /books/b123
返回的數據是:
{ id: 'b123', title: 'xxx', author: { id: 'u123' } }
這個時候,想要獲取完整的author資源,須要再調用GET /users/u123
。
然而,經過_embed參數,能夠一步就直接返回包含完整User資源的author連接,就像咱們一開始定義的那樣。調用GET /users/u123?\_embed=author
,返回如下的結果:
{ id: 'b123', title: 'xxx', author: { id: 'u123', name: 'yyy' } }
多個內嵌資源用逗號分隔便可。
操做的返回內容,它的表述格式是可選的。只限定爲JSON格式是一種可選的簡潔方案。
不一樣的操做類型,其參數和返回值模式是有必定規律性的。現總結以下:
這個操做請求的是一個資源集合,返回的是一個JSON數組。
其參數能包括:篩選、排序、分頁、內嵌。
這個操做請求的是一個個體資源,返回的是一個JSON對象。
其參數只包括:內嵌。
這個操做請求建立一個新資源,返回的是一個JSON對象,表述新建立的資源。
其參數就是該資源的表述。
這個操做請求更新一箇舊資源,返回的是一個JSON對象,表述更新後的資源。
其參數就是該資源的表述。
這個操做請求刪除一個資源,無返回值,無參數。
其餘操做視狀況而定,通常無返回值,無參數。
任何操做都會發生出錯狀況。出錯的緣由有不少種,有源於客戶端的,也有源於服務器的。有預料中的,也有預料以外的。對於出錯狀況,服務器要向客戶端發送一個狀態碼及附加一個JSON格式的錯誤消息(這裏像返回值的考慮同樣也只考慮JSON格式了)。一個例子就是:
401 Unauthorized { message: "沒登陸" }
這裏的message字段做爲錯誤狀態的描述,做爲解釋出錯的緣由。若是表述的合適,能夠做爲最終用戶的提示信息,直接在彈框中顯示。
這裏面沒有考慮加入更多的字段了,好比一個code字段來更細緻的區別錯誤的類型。這種考慮是基於客戶端對於接口調用出錯無能爲力,通常能作的就兩種:
關於用戶的受權在HTTP和Restful中的方案,市面上有不少種。這裏介紹的是一種Token機制。很簡單,用戶經過某個接口(例如/users/login
)獲取受權的Token,而後每次調用接口時將這個Token附加到Header Access-Token中。
用戶的Token不只用於受權,也用於標識用戶的身份。當須要傳遞用戶id的時候,每每發現用戶的id信息能夠從Token中獲取。舉個例子,id爲u123的用戶調用以下接口時:
GET /users/u123 Access-Token: 包含u123的受權信息
其中Token信息能夠從相應的Header中獲取,因此此時明確標明id u123沒有必要。此時能夠用一個佔位符()佔位一下便可。
GET /users/_token Access-Token: 包含u123的受權信息