在面向資源的 API 中,資源是命名實體,資源名稱是其識別符號。每個資源 必須( MUST ) 有唯一的資源名稱。資源名稱由資源自己的 ID,任一父資源的 ID 及其 API 服務名稱組成。下面我們將看一看資源 ID 和資源名是如何構成的。
gRPC API 應該為資源名使用無協議(scheme-less)的 URI。它們通常遵循 REST URL 慣例並且其行為與網路檔案路徑非常相似。它們能非常容易地對映到 REST API:詳細內容檢視標準方法。
集合是一種特殊型別的資源,它包含了相同型別子資源的列表。例如,目錄是檔案資源的集合。集合的資源 ID 叫做集合 ID。
資源名稱由集合 ID 和資源 ID 按層次組織形成,並以斜槓(/)分隔。如果資源包含子資源,子資源名稱的格式是父資源名稱後面加上子資源 ID,同樣地使用斜槓分隔。
例 1:一個儲存服務具有 buckets
集合,每個 bucket 具有 objects
集合:
| API 服務名 | 集合 ID | 資源 ID | 集合 ID | 資源 ID |
| - | - | - | - | - |
| //storage.googleapis.com | /buckets | /bucket-id | /objects| /object-id |
例 2:一個具有 users
集合的郵件服務,每個使用者具有 settings
子資源, settings
子資源具有 customFrom
和另外的子資源:
| API 服務名 | 集合 ID | 資源 ID | 資源 ID | 資源 ID |
| - | - | - | - | - |
| //mail.googleapis.com | /users | /name@example.com | /settings| /customFrom |
API 設計者可以為資源和集合 ID 選擇任何可接受的值,只要它們在資源層次結構中是唯一的即可。你可以在下面找到有關選擇適當資源和集合 ID 的更多指南。
完整資源名
無協議(scheme-less) URI 由相容 DNS 的 API 服務名和資源路徑組成。資源路徑也稱為相對資源名。例如:
"//library.googleapis.com/shelves/shelf1/books/book2"
API 服務名用於客戶端定位 API 服務端點,如果只為內部服務,它可以(may)是假的 DNS 名。如果 API 服務名在上下文中顯而易見的話則會經常使用相對資源名。
相對資源名
沒有斜槓(/)開頭的 URI 路徑標識了 API 服務中的資源。例如:
"shelves/shelf1/books/book2"
資源 ID
使用非空的 URI 段標識其父資源中的資源。請看上面的例子。
資源名稱後面跟隨的資源 ID 可以(may) 具有不只一個 URI 段,例如:
| 集合 ID | 資源 ID |
| - | - |
| files | /source/py/parser.py |
如果可以的話,API 服務應該(should)使用 URL 友好的資源 ID。資源 ID 必須(must) 明確地記錄在文件中,不管它們是由客戶端還是服務端分配的。例如,檔名一般由客戶端分配,而郵件資訊 ID 一般由服務端分配。
集合 ID
使用非空的 URI 段標識其父資源中的資源集合。請看上面的例子。
因為集合 ID 經常出現在生成的客戶端庫中,它們 必須(must) 符合以下要求:
必須(must) 是合法的 C/C++ 識別符號
必須(must) 是複數形式的首字母小寫的駝峰命名
必須(must) 使用清晰簡明的英語詞彙
-
應該(should) 避免或限定過於籠統的術語。例如:
RowValue
優於Value
。除非明確定義,否則 應該(should) 避免使用如下術語:Element
Entry
Instance
Item
Object
Resource
Type
Value
資源名 vs URL
完整的資源名類似普通的 URL,但它們並不相同。同樣的資源能夠通過不同版本或不同協議的 API 來暴露出去。完整的資源名並沒有指定這些資訊,所以必須將它對映到特定的協議和 API 版本上才能直接地使用。
為了通過 REST API 使用完整的資源名,必須(must) 使用如下方法將其對映為 REST URL:在服務名前新增 HTTPS 協議、在資源路徑前新增 API 主版本號、將資源路徑進行 URL 轉義。例如:
// 這是日曆事件的資源名
"//calendar.googleapis.com/users/john smith/events/123"
// 這是對應的 HTTP URL
"https://calendar.googleapis.com/v3/users/john%20smith/events/123"
資源名做為字串
除非有向後相容的問題,Google API 必須(must) 使用字串來表示資源名。資源名 應該(should) 像普通檔案路徑那樣處理,並且不支援百分號編碼。
對於資源定義,第一個欄位 應該(should) 是資源名稱的字串欄位,它 應該(should) 叫作 name
。
注意:像 display_name
、first_name
、last_name
、full_name
這種與名字相關的欄位 應該(should) 給出定義來避免混亂。
例子:
service LibraryService {
rpc GetBook(GetBookRequest) returns (Book) {
option (google.api.http) = {
get: "/v1/{name=shelves/*/books/*}"
};
};
rpc CreateBook(CreateBookRequest) returns (Book) {
option (google.api.http) = {
post: "/v1/{parent=shelves/*}/books"
body: "book"
};
};
}
message Book {
// book 的資源名。必須是"shelves/*/books/*"的格式
// 例如:"shelves/shelf1/books/book2".
string name = 1;
// ... 其他屬性
}
message GetBookRequest {
// 一個 book 的資源名。例如:"shelves/shelf1/books/book2"
string name = 1;
}
message CreateBookRequest {
// 建立 book 的父資源名
// 例如:"shelves/shelf1"
string parent = 1;
// 被建立的 book 資源。客戶端一定不能(must not)設定 `Book.name` 欄位
Book book = 2;
}
提示:為了資源名稱的一致性,開始的斜槓 一定不能(must not) 被 URL 模版變數捕獲。例如,必須(must) 使用 URL 模版 "/v1/{name=shelves/*/books/*}"
而不是 "/v1{name=/shelves/*/books/*}"
。