Google REST API 設(shè)計(jì)關(guān)鍵總結(jié)

本文摘抄至 Google Cloud API 設(shè)計(jì)指南(見附錄1),用于標(biāo)注在實(shí)踐該規(guī)范時(shí)一些關(guān)鍵注重點(diǎn)。(未完待續(xù)...)

簡介

這是互聯(lián)網(wǎng) API 的通用設(shè)計(jì)指南。它自 2014 年起在 Google 內(nèi)部使用,是 Google 在設(shè)計(jì) Cloud API 和其他 Google API 時(shí)遵循的指南。我們在此公開此設(shè)計(jì)指南,目的是為外部開發(fā)者提供信息,使我們所有人都能更輕松地協(xié)同工作。

HTTP 準(zhǔn)則

  • HTTP 請求和響應(yīng)主體使用 application/json 作為 Content-Type
    TODO 舉例 
    
  • 長請求網(wǎng)址(GET/DELETE)
    網(wǎng)址具有實(shí)際長度限制,通常在 2k-8k 之間,當(dāng)使用的 API 網(wǎng)址超過長度限制時(shí),可能會(huì)由于多方原因拒絕此請求。要避開該限制,客戶端應(yīng)設(shè)置 Content-Type: application/x-www-form-urlencoded 的 POST 請求,且 HTTP 標(biāo)頭為 X-HTTP-Method-Override: GET
    TODO 舉例 
    
  • 請求網(wǎng)址符合 REST 模型時(shí),應(yīng)將 HTTP 方法指定為 API 規(guī)范的一部分
    安全方法不應(yīng)表示檢索以外的操作(如 GET 和 HEAD),不應(yīng)對客戶端產(chǎn)生任何的副作用。
    HTTP 中的冪等性,意味著多個(gè)相同的請求產(chǎn)生的副作用與單個(gè)請求相同(GET/PUT/DELETE)


    image.png
  • 其他詳情查看附錄2

REST

什么是 REST API?

REST(Representational State Transfer) API 是可單獨(dú)尋址的“資源”(API 中的“名詞”)的“集合”。資源通過資源名稱被引用,并通過一組“方法”(也稱為“動(dòng)詞”或“操作”)進(jìn)行控制。
資源
面向資源的 API 通常被構(gòu)建為資源層次結(jié)構(gòu),其中每個(gè)節(jié)點(diǎn)是一個(gè)“簡單資源”或“集合資源”。 為方便起見,它們通常被分別稱為資源和集合。

  • 一個(gè)集合包含相同類型的資源列表。 例如,一個(gè)用戶擁有一組聯(lián)系人。
  • 資源具有一些狀態(tài)和零個(gè)或多個(gè)子資源。 每個(gè)子資源可以是一個(gè)簡單資源或一個(gè)集合資源。

資源名稱

// 書架上的書
shelves/${shelf1}/books/${book2}
// 資源名
- 必須是復(fù)數(shù)形式的小駝峰(如果沒有合適的復(fù)數(shù)形式,則使用單數(shù)形式)
- 必須使用簡明扼要的英文詞語
- 應(yīng)該避免使用過于籠統(tǒng)的詞語,或?qū)ζ湎薅ê笫褂茫ɡ?rowValues 優(yōu)先于 values),例如:elements/entries/instances/items/objects/resources/types/values
- 資源名需要網(wǎng)址轉(zhuǎn)義(URLEncode)
- 資源名為字符串
- 推薦使用資源名代替資源 ID 來標(biāo)識資源

方法

面向資源的 API 的關(guān)鍵特性是,強(qiáng)調(diào)資源(數(shù)據(jù)模型)甚于資源上執(zhí)行的方法(功能)。典型的面向資源的 API 使用少量方法公開大量資源。方法可以是標(biāo)準(zhǔn)方法或自定義方法。對于本指南,標(biāo)準(zhǔn)方法有:List、Get、Create、Update 和 Delete

示例

Gmail API 服務(wù)實(shí)現(xiàn)了 Gmail API 并公開了大多數(shù) Gmail 功能。它具有以下資源模型:

  • API 服務(wù):gmail.googleapis.com
    • 用戶集合:users/*。每個(gè)用戶都擁有以下資源。
      • 消息集合:users/*/messages/*。
      • 線程集合:users/*/threads/*。
      • 標(biāo)簽集合:users/*/labels/*。
      • 變更歷史記錄集合:users/*/history/*。
      • 表示用戶個(gè)人資料的資源:users/*/profile。
      • 表示用戶設(shè)置的資源:users/*/settings。

標(biāo)準(zhǔn)方法

標(biāo)準(zhǔn)方法可降低復(fù)雜性并提高一致性


image.png

List(列表)

常用于搜索資源,適用于來自單個(gè)集合的數(shù)據(jù),該集合大小有限且不進(jìn)行緩存
HTTP 映射

  • Method: GET
  • 響應(yīng)正文應(yīng)該包含資源列表,以及可選元數(shù)據(jù)
  • 接收資源名稱的請求消息字段應(yīng)該映射到網(wǎng)址路徑(資源主體標(biāo)識)
  • 所有剩余的請求消息字段應(yīng)該映射到網(wǎng)址查詢參數(shù)(query params)
// 分頁查詢場景
GET shelves/${shelf1}/books?page=1&pageSize=10&pageToken={上一頁的標(biāo)識}

{
  books: [...],
  nextPageToken: "..." // 可缺省
}
// TODO(d): 無分頁場景是否適用本規(guī)則?

常見狀態(tài)碼(HTTP)
- 200 資源獲取成功
- 4xx 一些請求錯(cuò)誤
- TODO

Get(獲?。?/h2>

返回指定資源
HTTP 映射

  • Method: GET
  • 響應(yīng)正文應(yīng)該包含資源列表,以及可選元數(shù)據(jù)
  • 接收資源名稱的請求消息字段應(yīng)該映射到網(wǎng)址路徑(資源主體標(biāo)識)
  • 所有剩余的請求消息字段應(yīng)該映射到網(wǎng)址查詢參數(shù)(query params)
GET shelves/${shelf1}/books/${encode('時(shí)間簡史')}?author=zhangsan

// 整個(gè)返回體為 Book 實(shí)例
{
    author: 'zhangsan',
    content: 'xxx'
}

常見狀態(tài)碼(HTTP)

  • 200 資源獲取成功
  • 404 找不到資源
  • 4xx 一些請求錯(cuò)誤
  • TODO

Create(創(chuàng)建)

在指定父資源下創(chuàng)建新資源,并返回新創(chuàng)建的資源。
HTTP 映射

  • Method: POST
  • 所有剩余的請求消息字段應(yīng)該映射到網(wǎng)址查詢參數(shù)
POST shelves/${shelf1}/books
// 請求正文為即將創(chuàng)建的資源
{
  name: 'xxx',
  author: 'xxx'
}
// 響應(yīng)正文
{
  name: 'xxx',
  author: 'xxx'
}

常見狀態(tài)碼(HTTP)

  • 200 資源創(chuàng)建成功(對于標(biāo)準(zhǔn)的 RESTful API 來說,創(chuàng)建成功對應(yīng) 201,但 Google 規(guī)范中,標(biāo)準(zhǔn) POST 不再用于更新場景,所以不存在語義上的沖突)
  • 4xx 一些請求錯(cuò)誤
  • TODO

Update(更新)

用于除了更新資源名或父資源屬性之外,可以改變所有可變資源(重命名或移動(dòng)應(yīng)使用自定義方法)
HTTP 映射(標(biāo)準(zhǔn))
Method: PATCH

  • 支持部分資源更新,并設(shè)置更新部分的字段掩碼
  • 包含資源的請求消息字段必須映射到請求正文
  • 所有剩余的請求消息字段必須映射到網(wǎng)址查詢參數(shù)
  • 響應(yīng)消息必須是更新的資源本身
PATCH shelves/${shelf1}/books/${bookName}

// 請求正文
{
    book: {
      name: 'xxx'
    },
    updateMask: 'book.name'
}
// 響應(yīng)正文
{
  name: 'xxx',
  author: 'xxx'
}

HTTP 映射(完整資源更新,不推薦,添加新字段時(shí)會(huì)存在向后兼容問題)

  • Method: PUT
  • 僅支持完整更新
  • 包含資源的請求消息字段必須映射到請求正文
  • 所有剩余的請求消息字段必須映射到網(wǎng)址查詢參數(shù)
  • 響應(yīng)消息必須是更新的資源本身
PUT shelves/${shelf1}/books/${bookName}

// 請求正文
{
    name: 'xxx', // 改變此字段
    author: 'xxx' // 不變此字段
}
// 響應(yīng)正文
{
  name: 'xxx',
  author: 'xxx'
}

常見狀態(tài)碼(HTTP)

  • 200 更新成功
  • 4xx 一些請求錯(cuò)誤
  • TODO

Delete(刪除)

用于刪除或計(jì)劃刪除指定資源,API 不應(yīng)依賴于該方法返回任何信息,因?yàn)椴荒苤貜?fù)調(diào)用。
HTTP 映射(完整資源更新,不推薦,添加新字段時(shí)會(huì)存在向后兼容問題)

  • Method: DELETE
  • 接收資源名稱的請求消息字段應(yīng)該映射到網(wǎng)址路徑
  • 所有剩余的請求消息字段應(yīng)該映射到網(wǎng)址查詢參數(shù)
  • 如果 Delete 方法立即移除資源,則應(yīng)該返回空響應(yīng)
  • 如果 Delete 方法啟動(dòng)長時(shí)間運(yùn)行的操作,則應(yīng)該返回長時(shí)間運(yùn)行的操作
  • 如果 Delete 方法僅將資源標(biāo)記為已刪除,則應(yīng)該返回更新后的資源
DELETE shelves/${shelf1}/books/${bookName}

常見狀態(tài)碼(HTTP)

  • 200 刪除成功
  • 404 資源不存在
  • 4xx 一些請求錯(cuò)誤
  • TODO

自定義方法

自定義方法是指 5 個(gè)標(biāo)準(zhǔn)方法之外的 API 方法。這些方法應(yīng)該僅用于標(biāo)準(zhǔn)方法不易表達(dá)的功能。通常情況下,API 設(shè)計(jì)者應(yīng)該盡可能優(yōu)先考慮使用標(biāo)準(zhǔn)方法,而不是自定義方法。標(biāo)準(zhǔn)方法具有大多數(shù)開發(fā)者熟悉的更簡單且定義明確的語義,因此更易于使用且不易出錯(cuò)。另一項(xiàng)優(yōu)勢是 API 平臺更加了解和支持標(biāo)準(zhǔn)方法,例如計(jì)費(fèi)、錯(cuò)誤處理、日志記錄、監(jiān)控。
自定義方法可以與資源、集合或服務(wù)關(guān)聯(lián)。 它可以接受任意請求和返回任意響應(yīng),并且還支持流式請求和響應(yīng)。

https://service.name/v1/some/resource/name:customVerb
  • 自定義方法應(yīng)使用 HTTP POST,因?yàn)樵搫?dòng)詞具有更靈活的語義。(作為替代 GET 或 LIST 的方法,可以使用 GET)
  • 自定義方法不應(yīng)該使用 HTTP PATCH(根據(jù)具體語義而定)

常用自定義方法

image.png

錯(cuò)誤

Google API 的錯(cuò)誤模型由 google.rpc.Status 邏輯定義,該實(shí)例在發(fā)生 API 錯(cuò)誤時(shí)返回給客戶端
格式(rpc)

package google.rpc;

message Status {
  // 客戶端可以輕松處理的簡單錯(cuò)誤代碼
  int32 code = 1;

  // 面向開發(fā)人員人類可讀的錯(cuò)誤信息,它應(yīng)該解釋錯(cuò)誤,并提供一個(gè)可行的解決方案
  string message = 2;

  // 一些額外的錯(cuò)誤信息,如重試信息或幫助鏈接

  repeated google.protobuf.Any details = 3;
}

格式(http)

// resp headers
Content-Type: application/json
Status: 404
// resp body
{
  "message": "NOT FOUND",
  "details": "" // 可選
}

單個(gè) API 應(yīng)避免定義其他錯(cuò)誤代碼,因?yàn)殚_發(fā)人員不太可能編寫用于處理大量錯(cuò)誤代碼的邏輯。作為參考,每個(gè) API 調(diào)用平均處理 3 個(gè)錯(cuò)誤代碼意味著大多數(shù)應(yīng)用邏輯僅用于錯(cuò)誤處理,這并不會(huì)帶來良好的開發(fā)者體驗(yàn)。

常見錯(cuò)誤狀態(tài)

image.png

命名規(guī)范

大規(guī)則:簡單、直觀、一致

  • 采用美式英語(如:使用 license(美) 而非 licence(英))
  • 可以使用已被廣泛接受的簡寫
  • 盡量使用常用詞匯(如:描述移除和銷毀,刪除優(yōu)于擦除)
  • 避免名稱過載。使用不同的名稱命名不同的概念
  • 避免過于籠統(tǒng)的命名
  • 集合 ID 采用小駝峰復(fù)數(shù)形式(如:members)

設(shè)計(jì)模式

列表分頁

可列表集合應(yīng)該支持分頁,即使結(jié)果通常很小

如果某個(gè) API 從一開始就不支持分頁,稍后再支持它就比較麻煩,因?yàn)樘砑臃猪摃?huì)破壞 API 的行為。 不知道 API 正在使用分頁的客戶端可能會(huì)錯(cuò)誤地認(rèn)為他們收到了完整的結(jié)果,而實(shí)際上只收到了第一頁

跨子集執(zhí)行 List/Search 操作

有時(shí),API 需要讓客戶跨子集執(zhí)行 List/Search 操作。例如,“API 圖書館”有一組書架,每個(gè)書架都有一系列書籍,而客戶希望在所有書架上搜索某一本書。在這種情況下,建議在子集合上使用標(biāo)準(zhǔn) List,并為父集合指定通配符集合 ID "-"。對于“API 圖書館”示例,我們可以使用以下 REST API 請求:
GET https://xxx/v1/shelves/-/books?filter=xxx

枚舉默認(rèn)值:0

每個(gè)枚舉定義必須以 0 值條目開頭,當(dāng)未明確指定枚舉值時(shí),應(yīng)使用該條目。API 必須記錄如何處理 0 值

部分響應(yīng)(與 List/Search 區(qū)別?)

通過特殊字段(如 Google 的 FieldMask)給予過濾響應(yīng)集合內(nèi)容

資源視圖

為了減少網(wǎng)絡(luò)流量,有時(shí)可允許客戶端限制服務(wù)器應(yīng)在其響應(yīng)中返回的資源部分,即返回資源視圖而不是完整的資源表示形式。API 中的資源視圖支持是通過向方法請求添加一個(gè)參數(shù)來實(shí)現(xiàn)的,該參數(shù)允許客戶端指定希望在響應(yīng)中接收的資源視圖

TODO

附錄

  1. Google Cloud API 設(shè)計(jì)指南

  2. HTTP 準(zhǔn)則詳細(xì)

  3. Google API 錯(cuò)誤模型詳情

  4. 當(dāng)前文稿原始地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 去年有段時(shí)間得空,就把谷歌GAE的API權(quán)威指南看了一遍,收獲頗豐,特別是在自己幾乎獨(dú)立開發(fā)了公司的云數(shù)據(jù)中心之后...
    騎單車的勛爵閱讀 21,080評論 0 41
  • 標(biāo)簽(空格分隔): google restful api design 當(dāng)前版本的API設(shè)計(jì)指南發(fā)布時(shí)間:2017...
    主君_05c4閱讀 4,033評論 0 5
  • Java繼承關(guān)系初始化順序 父類的靜態(tài)變量-->父類的靜態(tài)代碼塊-->子類的靜態(tài)變量-->子類的靜態(tài)代碼快-->父...
    第六象限閱讀 2,246評論 0 9
  • 歡迎關(guān)注公眾號“Tim在路上” 1.聽說你對JVM有點(diǎn)研究,講一講JVM的內(nèi)存模型吧(我說虛擬機(jī)棧,本地方法棧,程...
    Tim在路上閱讀 3,943評論 4 91
  • 前言:如果你有更好的私藏文章,不凡分享出來,獨(dú)樂樂不如眾樂樂(⊙o⊙) 本文總結(jié)了 RESTful API 設(shè)計(jì)相...
    utopia84閱讀 4,077評論 2 35

友情鏈接更多精彩內(nèi)容