Skip to content

Commit 1625d93

Browse files
authored
Adop AEP 127: HTTP and gRPC Transcoding (#159)
* original AIP-127 contents * Adop AEP 127: HTTP and gRPC Transcoding * review suggestions * addressing comments
1 parent 8da42f6 commit 1625d93

2 files changed

Lines changed: 125 additions & 5 deletions

File tree

aep/general/0127/aep.md.j2

Lines changed: 123 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,125 @@
11
# HTTP and gRPC Transcoding
22

3-
**Note:** This AEP has not yet been adopted. See
4-
[this GitHub issue](https://github.com/aep-dev/aep.dev/issues/51) for more
5-
information.
3+
APIs that follow [resource-oriented design][resources] are defined using
4+
[RPCs][rpc], but the resource-oriented design framework allows them to also be
5+
presented as APIs that largely follow REST/JSON conventions. This is important
6+
in order to help developers use their existing knowledge: over 80% of the
7+
public APIs available follow most REST conventions, and developers are
8+
accustomed to that pattern.
9+
10+
## Guidance
11+
12+
Protobuf APIs **must** provide HTTP definitions for each RPC that they define, except
13+
for bi-directional streaming RPCs, which can not be natively supported using
14+
HTTP/1.1. When providing a bi-directional streaming method, an API **should**
15+
also offer an alternative method that does not rely on bi-directional
16+
streaming.
17+
18+
### HTTP method and path
19+
20+
When using protocol buffers, each RPC **must** define the HTTP method and path
21+
using the [`google.api.http`][google.api.http] annotation:
22+
23+
```proto
24+
rpc CreateBook(CreateBookRequest) returns (Book) {
25+
option (google.api.http) = {
26+
post: "/v1/{parent=publishers/*}/books"
27+
body: "book"
28+
};
29+
}
30+
31+
message CreateBookRequest {
32+
// The publisher who will publish this book.
33+
// When using HTTP/JSON, this field is automatically populated based
34+
// on the URI, because of the `{parent=publishers/*}` syntax.
35+
string parent = 1 [
36+
(google.api.field_behavior) = REQUIRED,
37+
(google.api.resource_reference) = {
38+
child_type: "library.example.com/Book"
39+
}];
40+
41+
// The book to create.
42+
// When using HTTP/JSON, this field is populated based on the HTTP body,
43+
// because of the `body: "book"` syntax.
44+
Book book = 2 [(google.api.field_behavior) = REQUIRED];
45+
46+
// The user-specified ID for the book.
47+
// When using HTTP/JSON, this field is populated based on a query string
48+
// argument, such as `?bookId=foo`. This is the fallback for fields that
49+
// are not included in either the URI or the body.
50+
// Note that clients use camelCase format to communicate the field names
51+
// to the service.
52+
string book_id = 3;
53+
}
54+
```
55+
56+
- The first key (`post` in this example) corresponds to the HTTP method. RPCs
57+
**may** use `get`, `post`, `patch`, or `delete`.
58+
- RPCs **must** use the prescribed HTTP verb for each standard method, as
59+
discussed in [Get](/get), [List](/list), [Create](/create), [Update](/update), and
60+
[Delete](/delete)
61+
- RPCs **should** use the prescribed HTTP verb for custom methods, as
62+
discussed in [Custom Methods](/custom-methods).
63+
- RPCs **should not** use `put` or `custom`.
64+
- The corresponding value represents the URI.
65+
- URIs **must** use the `{foo=bar/*}` syntax to represent a variable that
66+
should be populated in the request proto. When extracting a [resource
67+
name](/resource-paths), the variable **must** include the entire resource name, not
68+
just the ID component.
69+
- URIs **may** use nested fields for their variable names. (Additionally,
70+
AEP-134 mandates this for `Update` requests.)
71+
- URIs **must** use the `*` character to represent ID components, which
72+
matches all URI-safe characters except for `/`. URIs **may** use `**` as
73+
the final segment of a URI if matching `/` is required.
74+
- The `body` key defines which single top-level field in the request will be
75+
sent as the HTTP body. If the body is `*`, then this indicates that the
76+
request object itself is the HTTP body. The request body is encoded as JSON
77+
as defined by protocol buffers' canonical [JSON encoding][json encoding].
78+
- RPCs **must not** define a `body` at all for RPCs that use the `GET` or
79+
`DELETE` HTTP verbs.
80+
- RPCs **must** use the prescribed `body` for Create ([Create](/create)) and Update
81+
([AEP-134](/update)) requests.
82+
- RPCs **should** use the prescribed `body` for custom methods ([Custom Methods](custom-methods)).
83+
- The `body` **must not** contain a nested field (or use the `.` character),
84+
- The `body` **must not** be the same as a URI parameter.
85+
- The `body` **must not** be a `repeated` field.
86+
- Fields **should not** use the `json_name` annotation to alter the field
87+
name in JSON, unless doing so for backwards-compatibility reasons.
88+
89+
**Note:** Bi-directional streaming RPCs should not include a `google.api.http`
90+
annotation at all. If feasible, the service **should** provide non-streaming
91+
equivalent RPCs.
92+
93+
### Multiple URI bindings
94+
95+
Occasionally, an RPC needs to correspond to more than one URI:
96+
97+
```proto
98+
rpc CreateBook(CreateBookRequest) returns (Book) {
99+
option (google.api.http) = {
100+
post: "/v1/{parent=publishers/*}/books"
101+
body: "book"
102+
additional_bindings: {
103+
post: "/v1/{parent=authors/*}/books"
104+
body: "book"
105+
}
106+
additional_bindings: {
107+
post: "/v1/books"
108+
body: "book"
109+
}
110+
};
111+
}
112+
```
113+
114+
- RPCs **may** define any number of additional bindings. The structure is
115+
identical to the `google.api.http` annotation (in fact, it is a recursive
116+
reference).
117+
- RPCs **must not** define an additional binding within an additional binding.
118+
- The `body` clause **must** be identical in the top-level annotation and each
119+
additional binding.
120+
121+
<!-- prettier-ignore-start -->
122+
[json encoding]: https://developers.google.com/protocol-buffers/docs/proto3#json
123+
[rpc]: https://en.wikipedia.org/wiki/Remote_procedure_call
124+
[google.api.http]: https://buf.build/googleapis/googleapis/docs/main:google.api#google.api.Http
125+
<!-- prettier-ignore-end -->

aep/general/0127/aep.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
id: 127
3-
state: reviewing
3+
state: approved
44
slug: transcoding
5-
created: 2023-01-22
5+
created: 2024-03-26
66
placement:
77
category: protobuf

0 commit comments

Comments
 (0)