Laravel 項(xiàng)目開發(fā)規(guī)范 API 設(shè)計(jì)規(guī)范

2023-02-16 17:12 更新

參考資料

首先請熟悉以下的兩個(gè)文檔:

API 設(shè)計(jì)上有無法抉擇的地方,應(yīng)該參考 GitHub 的 API 文檔:

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

API 版本控制

所有的 API,早期設(shè)計(jì)時(shí)都 必須 考慮版本控制。

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

將版本號直接加入 URL 中:

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

RESTful API

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

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

1. 使用 URL 定位資源

必須使用 URL 定位資源的規(guī)則。

在 RESTful 的架構(gòu)中,所有的一切都表示資源,每一個(gè) URL 都代表著一種資源,資源應(yīng)當(dāng)是一個(gè)名詞,而且大部分情況下是名詞的復(fù)數(shù),盡量不要在 URL 中出現(xiàn)動詞。

先來看看 GitHub 的 例子

GET /issues                                      列出所有的 issue
GET /orgs/:org/issues                            列出某個(gè)項(xiàng)目的 issue
GET /repos/:owner/:repo/issues/:number           獲取某個(gè)項(xiàng)目的某個(gè) issue
POST /repos/:owner/:repo/issues                  為某個(gè)項(xiàng)目創(chuàng)建 issue
PATCH /repos/:owner/:repo/issues/:number         修改某個(gè) issue
PUT /repos/:owner/:repo/issues/:number/lock      鎖住某個(gè) issue
DELETE /repos/:owner/:repo/issues/:number/lock   解鎖某個(gè) issue

例子中冒號開始的代表變量,例如 /repos/summerblue/larabbs/issues

在 GitHub 的實(shí)現(xiàn)中,我們可以總結(jié)出:

  • 資源的設(shè)計(jì)可以嵌套,表明資源與資源之間的關(guān)系。

  • 大部分情況下我們訪問的是某個(gè)資源集合,想得到單個(gè)資源可以通過資源的 id 或 number 等唯一標(biāo)識獲取。

  • 某些情況下,資源會是單數(shù)形式,例如某個(gè)項(xiàng)目某個(gè) issue 的鎖,每個(gè) issue 只會有一把鎖,所以它是單數(shù)。

? 錯(cuò)誤的例子:

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 應(yīng)該使用以下來定義資源路由:

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 設(shè)計(jì)了很多動詞,來表示不同的操作,RESTful 很好的利用的這一點(diǎn),我們需要正確的使用 HTTP 動詞,來表明我們要如何操作資源。

先來解釋一個(gè)概念,冪等性,指一次和多次請求某一個(gè)資源應(yīng)該具有同樣的副作用,也就是一次訪問與多次訪問,對這個(gè)資源帶來的變化是相同的。

常用的動詞及冪等性

動詞 描述 是否冪等
GET 獲取資源,單個(gè)或多個(gè)
POST 創(chuàng)建資源
PUT 更新資源,客戶端提供完整的資源數(shù)據(jù)
PATCH 更新資源,客戶端提供部分的資源數(shù)據(jù)
DELETE 刪除資源

為什么 PUT 是冪等的而 PATCH 是非冪等的,因?yàn)?nbsp;PUT 是根據(jù)客戶端提供了完整的資源數(shù)據(jù),客戶端提交什么就替換什么,而 PATCH 有可能是根據(jù)客戶端提供的參數(shù),動態(tài)的計(jì)算出某個(gè)值,例如每次請求后資源的某個(gè)參數(shù)減 1,所以多次調(diào)用,資源會有不同的變化。

另外需要注意的是,GET 請求對于資源來說是不安全的,絕不 通過 GET 請求改變(更新或創(chuàng)建)資源。

真實(shí)使用中,為了方便統(tǒng)計(jì)類的數(shù)據(jù),會有一些例外情況,例如帖子詳情,記錄訪問次數(shù),每調(diào)用一次,訪問次數(shù) +1。這種情況下可以考慮頁面展示成功后,再次調(diào)用一個(gè) POST 請求去更新閱讀數(shù)。

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

必須利用 HTTP 狀態(tài)碼和客戶端進(jìn)行通訊。

有一些 API 的設(shè)計(jì),不論接口的狀態(tài)成功與否,都會返回 200 ,然后使用自定的狀態(tài)碼,例如說 :

{
    // 數(shù)據(jù)不存在
    error_code: 30404
}

這種方法是不可取的。

HTTP 狀態(tài)碼是行業(yè)標(biāo)準(zhǔn),意味著成千上萬開發(fā)者都在認(rèn)同和使用這套規(guī)則,意味著他們寫出來的 HTTP 通訊程序(類庫)也在使用這套規(guī)則。所以沒有必要,也不該重新發(fā)明自己的一套規(guī)則。

HTTP 提供了豐富的狀態(tài)碼供我們使用,正確的使用狀態(tài)碼可以讓響應(yīng)數(shù)據(jù)更具可讀性。、

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

強(qiáng)制 User-Agent

強(qiáng)制客戶端在請求時(shí),必須發(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ù)后可以暫時(shí)不做處理,但是后續(xù)有特殊的業(yè)務(wù)需求時(shí),可以針對某個(gè)客戶端具體到版本,進(jìn)行特殊的數(shù)據(jù)處理。

常見的使用場景,是廢棄客戶端:例如一個(gè)銀行 APP,升級了交易時(shí)的加密算法,低于 5.0 版本的客戶端因?yàn)榘踩?,必須廢棄。針對此情況,可通過后端 API 判斷 User-Agent 標(biāo)頭,對低于 5.0 的版本的客戶端請求,返回專屬的數(shù)據(jù),如 APP 首頁的第一個(gè) Banner 顯示請升級客戶端,安全升級無法使用的提示。

現(xiàn)實(shí)生產(chǎn)中,有些客戶端用戶會關(guān)閉系統(tǒng)的應(yīng)用自動更新功能,多版本客戶端是無法避免的問題。有了 User-Agent ,我們可以更加靈活的做針對性處理。

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

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

  • /photos/create

  • /photos/{photo}

錯(cuò)誤的例子如:

  • /photo/create

  • /photo/{photo}


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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號