首先請熟悉以下的兩個文檔:
API 設計上有無法抉擇的地方,應該參考 GitHub 的 API 文檔:
GitHub 的 RESTful API 設計是業(yè)內(nèi)比較知名的。
所有的 API,早期設計時都 必須 考慮版本控制。
隨著業(yè)務的發(fā)展,需求的不斷變化,API 的迭代是必然的,很可能當前版本正在使用,而我們就得開發(fā)甚至上線一個不兼容的新版本,為了讓舊用戶可以正常使用,為了保證開發(fā)的順利進行,我們需要控制好 API 的版本。
將版本號直接加入 URL 中:
https://api.example.com/v1
https://api.example.com/v2
https://api.example.com/v3
開發(fā) API 時,必須使用 RESTful 規(guī)范來架構 API。
具體規(guī)則下面羅列出來。
必須使用 URL 定位資源的規(guī)則。
在 RESTful 的架構中,所有的一切都表示資源,每一個 URL 都代表著一種資源,資源應當是一個名詞,而且大部分情況下是名詞的復數(shù),盡量不要在 URL 中出現(xiàn)動詞。
先來看看 GitHub 的 例子:
GET /issues 列出所有的 issue
GET /orgs/:org/issues 列出某個項目的 issue
GET /repos/:owner/:repo/issues/:number 獲取某個項目的某個 issue
POST /repos/:owner/:repo/issues 為某個項目創(chuàng)建 issue
PATCH /repos/:owner/:repo/issues/:number 修改某個 issue
PUT /repos/:owner/:repo/issues/:number/lock 鎖住某個 issue
DELETE /repos/:owner/:repo/issues/:number/lock 解鎖某個 issue
例子中冒號開始的代表變量,例如 /repos/summerblue/larabbs/issues
在 GitHub 的實現(xiàn)中,我們可以總結出:
資源的設計可以嵌套,表明資源與資源之間的關系。
大部分情況下我們訪問的是某個資源集合
,想得到單個資源
可以通過資源的 id 或 number 等唯一標識獲取。
某些情況下,資源會是單數(shù)形式,例如某個項目某個 issue 的鎖
,每個 issue 只會有一把鎖,所以它是單數(shù)。
? 錯誤的例子:
POST https://api.example.com/createTopic
GET https://api.example.com/topic/show/1
POST https://api.example.com/topics/1/comments/create
POST https://api.example.com/topics/1/comments/100/delete
? 正確的例子:
POST https://api.example.com/topics
GET https://api.example.com/topics/1
POST https://api.example.com/topics/1/comments
DELETE https://api.example.com/topics/1/comments/100
Laravel 應該使用以下來定義資源路由:
Route::apiResource('users', UserController::class);
以上等同于:
Verb Path Action Route Name
GET /users index users.index
POST /users store users.store
GET /users/{user} show users.show
PUT|PATCH /users/{user} update users.update
DELETE /users/{user} destroy users.destroy
如果你不使用 apiResource()
方法,控制器方法 必須 按照以上的指紋來定義路由。
apiResource()
還可以使用以下方法來定制具體使用的路由:
Route::apiResource('photos', PhotoController::class)->only([
'index', 'show'
]);
Route:: apiResource('photos', PhotoController::class)->except([
'create', 'store', 'destroy'
]);
必須使用 HTTP 動詞來描述操作,絕不單一的使用 POST 來處理所有邏輯。
HTTP 設計了很多動詞,來表示不同的操作,RESTful 很好的利用的這一點,我們需要正確的使用 HTTP 動詞,來表明我們要如何操作資源。
先來解釋一個概念,冪等性
,指一次和多次請求某一個資源應該具有同樣的副作用,也就是一次訪問與多次訪問,對這個資源帶來的變化是相同的。
常用的動詞及冪等性
動詞 | 描述 | 是否冪等 |
---|---|---|
GET | 獲取資源,單個或多個 | 是 |
POST | 創(chuàng)建資源 | 否 |
PUT | 更新資源,客戶端提供完整的資源數(shù)據(jù) | 是 |
PATCH | 更新資源,客戶端提供部分的資源數(shù)據(jù) | 否 |
DELETE | 刪除資源 | 是 |
為什么 PUT 是冪等的而 PATCH 是非冪等的,因為 PUT 是根據(jù)客戶端提供了完整的資源數(shù)據(jù),客戶端提交什么就替換什么,而 PATCH 有可能是根據(jù)客戶端提供的參數(shù),動態(tài)的計算出某個值,例如每次請求后資源的某個參數(shù)減 1,所以多次調(diào)用,資源會有不同的變化。
另外需要注意的是,GET 請求對于資源來說是不安全的,絕不 通過 GET 請求改變(更新或創(chuàng)建)資源。
真實使用中,為了方便統(tǒng)計類的數(shù)據(jù),會有一些例外情況,例如帖子詳情,記錄訪問次數(shù),每調(diào)用一次,訪問次數(shù) +1。這種情況下可以考慮頁面展示成功后,再次調(diào)用一個 POST 請求去更新閱讀數(shù)。
必須利用 HTTP 狀態(tài)碼和客戶端進行通訊。
有一些 API 的設計,不論接口的狀態(tài)成功與否,都會返回 200 ,然后使用自定的狀態(tài)碼,例如說 :
{
// 數(shù)據(jù)不存在
error_code: 30404
}
這種方法是不可取的。
HTTP 狀態(tài)碼是行業(yè)標準,意味著成千上萬開發(fā)者都在認同和使用這套規(guī)則,意味著他們寫出來的 HTTP 通訊程序(類庫)也在使用這套規(guī)則。所以沒有必要,也不該重新發(fā)明自己的一套規(guī)則。
HTTP 提供了豐富的狀態(tài)碼供我們使用,正確的使用狀態(tài)碼可以讓響應數(shù)據(jù)更具可讀性。、
強制客戶端在請求時,必須發(fā)送 User-Agent 信息。
User-Agent 信息包含兩部分,客戶端信息 + 版本,使用斜桿分隔:
User-Agent: Mixin Bot iOS/2.1.37
User-Agent: Mixin Bot Android/2.1.22
User-Agent: MixPay PHP SDK/2.1.22
User-Agent: MixPay GO SDK/2.1.22
API 后端接收到 User-Agent 數(shù)據(jù)后可以暫時不做處理,但是后續(xù)有特殊的業(yè)務需求時,可以針對某個客戶端具體到版本,進行特殊的數(shù)據(jù)處理。
常見的使用場景,是廢棄客戶端:例如一個銀行 APP,升級了交易時的加密算法,低于 5.0 版本的客戶端因為安全原因,必須廢棄。針對此情況,可通過后端 API 判斷 User-Agent 標頭,對低于 5.0 的版本的客戶端請求,返回專屬的數(shù)據(jù),如 APP 首頁的第一個 Banner 顯示請升級客戶端,安全升級無法使用的提示。
現(xiàn)實生產(chǎn)中,有些客戶端用戶會關閉系統(tǒng)的應用自動更新功能,多版本客戶端是無法避免的問題。有了 User-Agent ,我們可以更加靈活的做針對性處理。
資源路由路由 URI 必須 使用復數(shù)形式,如:
/photos/create
/photos/{photo}
錯誤的例子如:
/photo/create
/photo/{photo}
更多建議: