# REST / Resource Oriented Design / Resource Modeling
## Design flow
- 確定資源類型 Determine what types of resources an API provides.
- 確定資源間的關係 Determine the relationships between resources.
- 根據類型及關係命名 Decide the resource name schemes based on types and relationships.
- 決定資源結構 Decide the resource schemas.
- 資源使用方法最小化 Attach minimum set of methods to resources.
## Resource vs Collection
萬物皆 resource,相同類型的 resource 集合稱為 collection,collection 也是一種 resource。
> A **collection** contains a list of **resources of the same type**. For example, a user has a collection of contacts.
>
> A **resource** has some state and zero or more sub-resources. Each sub-resource can be either a simple resource or a collection resource.
Collection 命名需使用複數形式,且避免過於籠統的命名。
## [Resource Naming](https://restfulapi.net/resource-naming/)
- 善用 `/` 來表達階層關係
> Use forward slash `/` to indicate hierarchical relationships.
>
> ```
> http://api.example.com/school/classes/{id}/students/{id}
> ```
- 屁屁不要加斜線
> Do not use trailing forward slash `/` in URIs.
>
> As the last character within a URI’s path, a forward slash `/` adds no semantic value and may cause confusion.
- 用 `-` 增加可讀性
> Use hyphens `-` to improve the readability of URIs.
- 不要用底線
> Do not use underscores `_`. Depending on the application’s font, it’s possible that the underscore `_` character can either get partially obscured or completely hidden in some browsers or screens.
- 全小寫
> Use lowercase letters in URIs.
- 不帶 file extension,真的想帶可以透過 `Content-Type`
> Do not use file extentions. If you want to highlight the media type of API using file extenstion then you should rely on the media type, as communicated through the Content-Type header, to determine how to process the body’s content.
- Punctuation for lists
> When there is no hierarchical relationship (such as in lists), punctuation marks such as the semicolon, or, more frequently, the comma should be used.
>
> Example: `/users/{id1},{id2}` to access multiple user resources
## Methods
### [Standard methods](https://cloud.google.com/apis/design/standard_methods)
減少複雜度,增加一致性,所以更好被使用。
> Standard methods reduce complexity and increase consistency.
REST Google APIs 基本五款:**`List`** 、 **`Get`** 、 **`Create`** 、 **`Update`** 、 **`Delete`**。
#### `List`
| Standard Method | HTTP Mapping | HTTP Request Body | HTTP Response Body |
|---|---|---|---|
| `List` | GET <collection URL> | N/A | Resource* list |
常用於搜尋功能,適合來自大小有限、沒 cache 的單一 collection。
> List is commonly used to search for resources.
> List is suited to data from a single collection that is bounded in size and not cached.
因為 collection 常變動,不可以 cache,resource 很大,但顯示出來應該要小。
常見的 pattern 有兩種:[Pagination](https://cloud.google.com/apis/design/design_patterns#list_pagination) 和 [Sorting Order](https://cloud.google.com/apis/design/design_patterns#sorting_order)。
##### [Pagination](https://cloud.google.com/apis/design/design_patterns#list_pagination)
儘管 response 很小,也應該支援 pagination。一開始如果沒有支援,後面再支援會很麻煩,因為它會破壞 API 的行為,使用者會誤以為自己拿到全部的結果,但其實只有拿到第一頁。
> Listable collections should support pagination, even if results are typically small.
>
> If an API does not support pagination from the start, supporting it later is troublesome because adding pagination breaks the API's behavior. Clients that are unaware that the API now uses pagination could incorrectly assume that they received a complete result, when in fact they only received the first page.
##### [Sorting Order](https://cloud.google.com/apis/design/design_patterns#sorting_order)
如果結果是有排序的,就該揭露 `order_by` 的資訊,預設是升冪,如果要降冪需特別註記在後方。
> If an API method lets client specify sorting order for list results, the request message should contain a field `order_by`.
>
> The default sorting order is ascending. To specify descending order for a field, a suffix "desc" should be appended to the field name. For example: "foo desc,bar".
#### `Get`
| Standard Method | HTTP Mapping | HTTP Request Body | HTTP Response Body |
|---|---|---|---|
| `Get` | GET <resource URL> | N/A | Resource* |
#### `Create`
| Standard Method | HTTP Mapping | HTTP Request Body | HTTP Response Body |
|---|---|---|---|
| `Create` | POST <collection URL> | Resource | Resource* |
#### `Update`
| Standard Method | HTTP Mapping | HTTP Request Body | HTTP Response Body |
|---|---|---|---|
| `Update` | PUT or PATCH <resource URL> | Resource | Resource* |
返回更新後的資源。
如果是重新命名或是移動資源,都不該使用 `Update` ,而該使用 custom method。
> Any functionality to rename or move a resource must not happen in the `Update` method and instead shall be handled by a custom method.
#### `Delete`
| Standard Method | HTTP Mapping | HTTP Request Body | HTTP Response Body |
|---|---|---|---|
| `Delete` | DELETE <resource URL> | N/A | google.protobuf.Empty** |
> If the `Delete` method **immediately removes** the resource, it should return an **empty response**.
>
> If the `Delete` method initiates a **long-running operation**, it should return the **long-running operation**.
>
> If the `Delete` method only marks the resource as **being deleted**, it should return the **updated resource**.
>
> The standard `Delete` method should return `google.protobuf.Empty`, unless it is performing a "soft" delete, in which case the method should return the resource with its state updated to indicate the deletion in progress.
第一次可以刪除,正常回應,但之後再刪除應該要回 `NOT_FOUND` 。
### [Custom methods](https://cloud.google.com/apis/design/custom_methods)
用 standard methods 不好表達意思的可以用 custom methods。
> Custom methods refer to API methods besides the 5 standard methods. They should only be used for functionality that cannot be easily expressed via standard methods.
Standard methods 當然還是最佳選擇,使用者比較熟悉使用且不容易誤解。
> Standard Methods have simpler and well-defined semantics that most developers are familiar with, so they are easier to use and less error prone.
用起來像這樣:
```
https://service.name/v1/some/resource/name:customVerb
```
> The reason to use `:` instead of `/` to separate the custom verb from the resource name is to support arbitrary paths.
> [color=red]
## 參考資料
- [API Design Guide / Google](https://cloud.google.com/apis/design/)
- [REST API Tutorial](https://restfulapi.net/)