Skip to content

Commit

Permalink
feat(137): add apply AEP
Browse files Browse the repository at this point in the history
add a new standard method to document apply / PUT.

This AEP is useful for:

- APIs that would like to offer a PUT endpoint, but has lacked
  guidance from the AEPs.
- APIs that would like to expose a declarative-friendly API 
  endpoint (the integration of which is simpler than apply).

Apply can also serve as an alternative to expose a create and update
endpoint.
  • Loading branch information
toumorokoshi committed Nov 13, 2024
1 parent 53da5a2 commit ec17fde
Show file tree
Hide file tree
Showing 8 changed files with 951 additions and 581 deletions.
12 changes: 2 additions & 10 deletions aep/general/0133/aep.md.j2
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,7 @@ Create methods are specified using the following pattern:

{% tab proto %}

```proto
rpc CreateBook(CreateBookRequest) returns (Book) {
option (google.api.http) = {
post: "/v1/{parent=publishers/*}/books"
body: "book"
};
option (google.api.method_signature) = "parent,book";
}
```
{% sample '../example.proto', 'rpc CreateBook' %}

- The RPC's name **must** begin with the word `Create`. The remainder of the
RPC name **should** be the singular form of the resource being created.
Expand All @@ -53,7 +45,7 @@ rpc CreateBook(CreateBookRequest) returns (Book) {
{% tab oas %}

```http
POST /v1/publishers/{publisher}/books?id=foo HTTP/2
POST /v1/publishers/{publisher}/books?id={book} HTTP/2
Host: bookstore.example.com
Accept: application/json
{
Expand Down
1 change: 1 addition & 0 deletions aep/general/0133/aep.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ slug: create
created: 2023-03-08
placement:
category: standard-methods
order: 30
1 change: 1 addition & 0 deletions aep/general/0134/aep.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ slug: update
created: 2023-01-22
placement:
category: standard-methods
order: 40
1 change: 1 addition & 0 deletions aep/general/0135/aep.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ slug: delete
created: 2024-02-11
placement:
category: standard-methods
order: 60
143 changes: 143 additions & 0 deletions aep/general/0137/aep.md.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Apply

In REST APIs, it is customary to make a `PUT` request to a collection's URI (for
example, `/v1/publishers/{publisher}/books`) in order to create or update a new
resource within that collection.

Resource-oriented design (AEP-121) honors this pattern through the `Apply`
method. These RPCs accept the parent collection and the resource to create or
update, and return the final resource.

## Guidance

APIs **should** provide an apply method for resources unless it is not valuable
for users to do so.

### Operation

Apply methods are specified using the following pattern:

- The HTTP verb **must** be `PUT`.
- Some resources take longer to be applied than is reasonable for a regular API
request. In this situation, the API **should** use a [long-running
operation](/long-running-operations).

{% tab proto %}

{% sample '../example.proto', 'rpc ApplyBook' %}

- The RPC's name **must** begin with the word `Apply`. The remainder of the
RPC name **should** be the singular form of the resource being applied.
- The request message **must** match the RPC name, with a `Request` suffix.
- The collection's parent resource **must** be called `parent`, and
**should** be the only variable in the URI path.
- The collection identifier (`books` in the above example) **must** be a
literal string.
- There **must** be a `body` key in the `google.api.http` annotation, and it
**must** map to the resource field in the request message.
- All remaining fields **should** map to URI query parameters.
- There **should** be exactly one `google.api.method_signature` annotation,
with a value of `"parent,{resource},id"`, or "`"parent,{resource}"` if the
resource ID is not required.
- The operation **must** have [strong consistency][].

{% tab oas %}

```http
PUT /v1/publishers/{publisher}/books/{book} HTTP/2
Host: bookstore.example.com
Accept: application/json
{
"title": "Pride and Prejudice",
"author": "Jane Austen"
}
```

{% endtabs %}

### Requests

Apply methods implement a common request message pattern:

- A `path` **must** be supported, and map to the URI path.
- The resource **must** be included and **must** map to the POST body.
- The request message **must not** contain any other required fields and
**should not** contain other optional fields except those described in this
or another AEP.

{% tab proto %}

{% sample '../example.proto', 'message ApplyBookRequest' %}

- A `path` field **must** be included, that is the path of the resource to apply.
- The field **must** be [annotated as `REQUIRED`][aep-203].
- The field **must** identify the [resource type][aep-4] of the resource
being applied.
- The request message **must not** contain any other required fields and
**should not** contain other optional fields except those described in this
or another AEP.

{% tab oas %}

{% sample '../example.oas.yaml', '$.paths./publishers/{publisher}/books/{book}.put.requestBody' %}

- The request body **must** be the resource being applied.

{% endtabs %}

### Responses

- The response **must** be the resource itself. There is no separate response
schema.
- The response **should** include the fully-populated resource, and **must**
include any fields that were provided unless they are input only (see
AEP-203).

{% tab proto %}

{% sample '../example.proto', 'message Book' %}

{% tab oas %}

{% sample '../example.oas.yaml', '$.paths./publishers/{publisher}/books/{book}.put.responses.200' %}

{% endtabs %}

### Errors

See [errors][], in particular [when to use PERMISSION_DENIED and NOT_FOUND
errors][permission-denied].

## Interface Definitions

{% tab proto %}

{% sample '../example.proto', 'rpc ApplyBook' %}

{% sample '../example.proto', 'message ApplyBookRequest' %}

{% sample '../example.proto', 'message Book' %}

{% tab oas %}

{% sample '../example.oas.yaml', '$.paths./publishers/{publisher}/books/{book}.put' %}

{% endtabs %}

## Further reading

- For ensuring idempotency in `Apply` methods, see AEP-155.
- For naming resources involving Unicode, see AEP-210.

[aep-121]: ./0121.md
[aep-122]: ./0122.md
[aep-4]: ./0004.md
[aep-155]: ./0155.md
[aep-203]: ./0203.md
[aep-210]: ./0210.md
[data plane]: ./0111.md#data-plane
[errors]: ./0193.md
[field_behavior]: ./203.md
[Declarative clients]: ./0003.md#declarative-clients
[permission-denied]: ./0193.md#permission-denied
[strong consistency]: ./0121.md#strong-consistency
8 changes: 8 additions & 0 deletions aep/general/0137/aep.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
id: 137
state: approved
slug: apply
created: 2024-11-13
placement:
category: standard-methods
order: 50
Loading

0 comments on commit ec17fde

Please sign in to comment.