Laravel 項目開發(fā)規(guī)范 API 設計規(guī)范

2023-02-16 17:12 更新

參考資料

首先請熟悉以下的兩個文檔:

API 設計上有無法抉擇的地方,應該參考 GitHub 的 API 文檔:

GitHub 的 RESTful API 設計是業(yè)內(nèi)比較知名的。

API 版本控制

所有的 API,早期設計時都 必須 考慮版本控制。

隨著業(yè)務的發(fā)展,需求的不斷變化,API 的迭代是必然的,很可能當前版本正在使用,而我們就得開發(fā)甚至上線一個不兼容的新版本,為了讓舊用戶可以正常使用,為了保證開發(fā)的順利進行,我們需要控制好 API 的版本。

將版本號直接加入 URL 中:

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

RESTful API

開發(fā) API 時,必須使用 RESTful 規(guī)范來架構 API。

具體規(guī)則下面羅列出來。

1. 使用 URL 定位資源

必須使用 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

2. Laravel 中使用資源路由

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'
]);

3. 使用 HTTP 動詞描述操作

必須使用 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ù)。

4. 使用 HTTP 狀態(tài)碼進行通訊

必須利用 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ù)更具可讀性。、

  • 200 OK - 對成功的 GET、PUT、PATCH 或 DELETE 操作進行響應。也可以被用在不創(chuàng)建新資源的 POST 操作上
  • 201 Created - 對創(chuàng)建新資源的 POST 操作進行響應。應該帶著指向新資源地址的 Location 頭
  • 202 Accepted - 服務器接受了請求,但是還未處理,響應中應該包含相應的指示信息,告訴客戶端該去哪里查詢關于本次請求的信息
  • 204 No Content - 對不會返回響應體的成功請求進行響應(比如 DELETE 請求)
  • 304 Not Modified - HTTP 緩存 header 生效的時候用
  • 400 Bad Request - 請求異常,比如請求中的 body 無法解析
  • 401 Unauthorized - 沒有進行認證或者認證非法
  • 403 Forbidden - 服務器已經(jīng)理解請求,但是拒絕執(zhí)行它
  • 404 Not Found - 請求一個不存在的資源
  • 405 Method Not Allowed - 所請求的 HTTP 方法不允許當前認證用戶訪問
  • 410 Gone - 表示當前請求的資源不再可用。當調(diào)用老版本 API 的時候很有用
  • 415 Unsupported Media Type - 如果請求中的內(nèi)容類型是錯誤的
  • 422 Unprocessable Entity - 用來表示校驗錯誤
  • 429 Too Many Requests - 由于請求頻次達到上限而被拒絕訪問

強制 User-Agent

強制客戶端在請求時,必須發(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 ,我們可以更加靈活的做針對性處理。

單數(shù) or 復數(shù)?

資源路由路由 URI 必須 使用復數(shù)形式,如:

  • /photos/create

  • /photos/{photo}

錯誤的例子如:

  • /photo/create

  • /photo/{photo}


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號