Google API設計指南-資源名稱

weixin_33840661發表於2017-04-04

翻譯自 API Design Guide - Resource Names

在面向資源的 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_namefirst_namelast_namefull_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/*}"

檢視其他章節

相關文章