此章節定義標準方法 List
、Get
、Create
、Update
和 Delete
。標準方法存在的意義是普遍的 API 中許多 API 方法具備很是類似的語義,經過將這些相似的 API 融合到標準方法中,咱們能夠顯著下降複雜性並提升一致性。以 Google APIs 爲例,超過 70% 是標準方法,這讓它們更加易於學習和使用。git
下表描述瞭如何將它們映射爲 REST 方法,也稱爲 CRUD 方法:github
| 方法 | HTTP 映射 | HTTP 請求體 | HTTP 響應體 |
| - | - | - | - |
| List | GET <集合 URL> | 空 | 資源[1]列表 |
| Get | GET <資源 URL> | 空 | 資源[1] |
| Create | POST <集合 URL> | 資源 | 資源[1] |
| Update | PUT 或 PATCH <資源 URL> | 資源 | 資源[1] |
| Delete | DELETE <資源 URL> | 空 | 空[2] |api
[1] List
、Get
、Create
和 Update
方法支持字段掩碼時,返回的資源 可能(may) 只包含部分數據。在某些狀況下,API 平臺會對全部方法原生支持字段掩碼。緩存
[2] 不當即刪除資源(好比經過更新標誌位或會執行時間較長的刪除操做)的 Delete
方法返回的響應 應該(should) 包含長時間運行的操做或被修改的資源。ide
標準方法也 能夠(may) 爲不能在一個 API 調用週期完成的請求返回長期運行的操做。post
下面章節詳細描述了每個標準方法。這些例子展現了在 .proto 文件中定義的方法,其中包含用於 HTTP 映射的特殊註釋。你能夠在 Google APIs 項目中找到許多使用標準方法的例子。學習
List
方法接收資源名和零個或多個其它參數作爲輸入,返回符合輸入的資源列表。它也一般被用來搜索資源。ui
List
適合取得沒有緩存且大小有限的來自單個集合的數據。對於更普遍的狀況,應該(should) 使用自定義方法。google
應該使用自定義的 BatchGet
方法來實現批量獲取(例如接收多個資源 ID而後返回對應的資源),而不是使用 List
。但若是已存在可以提供一樣功能的 List
方法,你 能夠(may) 爲此目的重用 List
方法。若是你在使用自定義的 BatchGet
方法,應該(should) 將它映射成 HTTP GET
。
HTTP 映射:
List
方法 必須(must) 使用 HTTP GET
動詞。
應該(should) 把要列出集合的資源名字放在 URL path 參數中。若是集合名映射到 URL path 中,URL 模版的最後一段(集合 ID) 必須(must) 是常量。
全部其餘的請求信息字段 必須(shall) 映射到 URL 的 query 參數中。
沒有請求體,API 配置中必定不能(must not) 定義 body
。
響應體 應該(should) 包含資源列表和可選的元數據。
// 列出指定書架上的全部圖書 rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) { // List 方法映射爲 HTTP GET option (google.api.http) = { // `parent` 獲取父資源名,例如 "shelves/shelf1" get: "/v1/{parent=shelves/*}/books" }; } message ListBooksRequest { // 父資源名稱,例如 "shelves/shelf1". string parent = 1; // 返回值的最大條數 int32 page_size = 2; // 從上一個 List 請求返回的 next_page_token 值(若是存在) string page_token = 3; } message ListBooksResponse { // 字段名應該匹配方法名中的名詞 "books",根據請求中的 page_size 字段,將會返回最大數量的條目 repeated Book books = 1; // 用於取得下一頁結果的值,沒有時爲空 string next_page_token = 2; }
GET
方法接收資源名,零個或多個參數,返回指定的資源。
HTTP 映射:
Get
方法 必須(must) 使用 HTTP GET
動詞。
表示資源名的請求信息字段 應該(should) 映射到 URL path 參數中。
全部其餘的請求信息字段 必須(shall) 映射到 URL 的 query 參數中。
沒有請求體,API 配置中必定不能(must not) 定義 body
。
返回的資源 必須(shall) 填充整個響應體。
// 取得指定的 book rpc GetBook(GetBookRequest) returns (Book) { // Get 映射爲 HTTP GET。資源名映射到 URL 中。沒有請求體 option (google.api.http) = { // 注意 URL 中用於獲取資源名的模板變量,例如 "shelves/shelf1/books/book2" get: "/v1/{name=shelves/*/books/*}" }; } message GetBookRequest { // 此字段包含被請求資源的名字,例如:"shelves/shelf1/books/book2" string name = 1; }
Create
方法接收一個集合名、零個或多個參數,在指定集合中建立一個新的資源並將其返回。
若是 API 支持建立資源,它 應該(should) 在全部可被建立的資源上具備 Create
方法 。
HTTP 映射:
Create
方法 必須(must) 使用 HTTP POST
動詞。
請求消息中 應該(should) 含有名爲 parent
的字段來接收新建資源的父資源名。
全部其餘的請求信息字段 必須(shall) 映射到 URL 的 query 參數中。
請求 能夠(may) 包含名爲 <resource>_id
的字段名來容許調用者選擇一個客戶端分配的 ID。這個字段 必須(must) 映射到 URL query 參數中。
包含資源的請求信息字段 應該(should) 映射到請求體中。若是 Create
方法使用了 HTTP 配置中的 body
字段,那麼 必須(must) 使用 body: "<resource_field>"
這種格式。
返回的資源 必須(shall) 填充到整個響應體。
若是 Create
方法支持客戶端指定資源名,當資源名已存在時請求 應該(should) 失敗(推薦(recommended) 使用 google.rpc.Code.ALREADY_EXISTS
)或者服務端分配另外的名字,而且文檔中應該明確指出建立的資源名可能會與傳入的名字不一樣。
rpc CreateBook(CreateBookRequest) returns (Book) { // Create 映射爲 HTTP POST,URL path 作爲集合名稱 // HTTP 請求體中包含資源 option (google.api.http) = { // 經過 `parent` 獲取父資源名,例如 "shelves/1" post: "/v1/{parent=shelves/*}/books" body: "book" }; } message CreateBookRequest { // 將被建立的 book 的父資源名 string parent = 1; // book 使用的 ID string book_id = 3; // 資源 book 將被建立,字段名應該與方法名中的名詞相匹配 Book book = 2; } rpc CreateShelf(CreateShelfRequest) returns (Shelf) { option (google.api.http) = { post: "/v1/shelves" body: "shelf" }; } message CreateShelfRequest { Shelf shelf = 1; }
Update
方法接收包含資源和零個或多個參數的請求,更新指定的資源和屬性並返回更新後的資源。
可修改的資源屬性 應該(should) 使用 Update
方法來更新,除非屬性中包含資源名或父資源。任何重命名或移動資源的操做 必定不要(must not) 經過 Update
執行,必須(shall) 經過自定義方法處理。
HTTP 映射:
標準的 Update
方法 應該(should) 支持資源的部分更新,使用帶有名爲 update_mask
的 FieldMask
字段的 HTTP 動詞 PATCH
來執行操做。
應該(should) 使用自定義方法來實現更高級的 Update
方法,例如追加劇復的字段。
若是 Update
方法僅支持資源的完整更新,則 必須(must) 使用 HTTP 動詞 PUT
實現。然而並不鼓勵這樣作,由於當添加新的資源字段時會有後向兼容的問題。
被修改資源的名稱字段 必須(must) 映射到 URL path 參數中。此字段也 能夠(may) 加在資源信息中。
包含資源的請求信息 必須(must) 映射到請求體中。
全部其餘請求信息 必須(must) 映射到 URL query 參數中。
返回響應中的資源信息 必須(must) 是被修改的資源。
若是 API 接收客戶端分配的資源名,那麼服務端 能夠(may) 容許客戶端指定一個不存在的資源名來建立新的資源。不然,Update
方法應該(should) 由於不存在的資源名而失敗。當資源名不存在是惟一錯誤時,應該(should) 使用錯誤碼 NOT_FOUND
。
即便 API 的 Update
方法可以新建資源,它也 應該(should) 提供 Create
方法。這是由於只有 Update
方法可以新建資源會讓人迷惑。
rpc UpdateBook(UpdateBookRequest) returns (Book) { // Update 映射爲 HTTP PATCH。資源名映射到 URL path 參數中 // 資源包含在 HTTP 請求體中 option (google.api.http) = { // 注意用於獲取待更新 book 的資源名的 URL 模版變量 patch: "/v1/{book.name=shelves/*/books/*}" body: "book" }; } message UpdateBookRequest { // 替換服務端上的 book 資源 Book book = 1; // 用於資源更新的掩碼 // `FieldMask` 的定義請參考 https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#fieldmask FieldMask update_mask = 2; }
Delete
方法接收資源名和零個或多個參數,而後刪除或準備刪除指定資源。Delete
方法 應該(should) 返回 google.protobuf.Empty
。
注意,API 不該該(should not) 依賴 Delete
方法返回的任何信息,由於它不能重複調用。
HTTP 映射:
Delete
方法 必須(must) 使用 HTTP DELETE
動詞
表示資源名的請求信息字段 應該(should) 映射到 URL path 參數中
全部其餘的請求信息字段 必須(shall) 映射到 URL 的 query 參數中
沒有請求體,API 配置 必定不要(must not) 定義 body
Delete
方法直接刪除資源時,應該(should) 返回空的響應
Delete
方法初始化一個長時間的操做時,應該(should) 返回這個操做
Delete
方法將資源標記爲被刪除時,應該(should) 返回更新後的資源
Delete
方法的調用在效果上應該是冪等的,但並不須要有相同的返回值。任意次 Delete
請求的結果 應該(should) 是資源被刪除,但只有第一次請求應該返回正確,後續的請求應該返回 google.rpc.Code.NOT_FOUND
。
rpc DeleteBook(DeleteBookRequest) returns (google.protobuf.Empty) { // Delete 映射爲 HTTP DELETE。資源名映射到 URL path 參數中 // 沒有請求體 option (google.api.http) = { // 注意 URL 模板變量獲取待刪除資源的名稱,例如 "shelves/shelf1/books/book2" delete: "/v1/{name=shelves/*/books/*}" }; } message DeleteBookRequest { // 待刪除的資源名稱,例如 "shelves/shelf1/books/book2" string name = 1; }