AIP-127
HTTP and gRPC Transcoding
APIs that follow resource-oriented design are defined using RPCs, but the resource-oriented design framework allows them to also be presented as APIs that largely follow REST/JSON conventions. This is important in order to help developers use their existing knowledge: over 80% of the public APIs available follow most REST conventions, and developers are accustomed to that pattern.
Guidance
APIs must provide HTTP definitions for each RPC that they define, except for bi-directional streaming RPCs, which can not be natively supported using HTTP/1.1. When providing a bi-directional streaming method, an API should also offer an alternative method that does not rely on bi-directional streaming.
HTTP method and path
When using protocol buffers, each RPC must define the HTTP method and path
using the google.api.http
annotation:
rpc CreateBook(CreateBookRequest) returns (Book) {
option (google.api.http) = {
post: "/v1/{parent=publishers/*}/books"
body: "book"
};
}
message CreateBookRequest {
// The publisher who will publish this book.
// When using HTTP/JSON, this field is automatically populated based
// on the URI, because of the `{parent=publishers/*}` syntax.
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {
child_type: "library.googleapis.com/Book"
}];
// The book to create.
// When using HTTP/JSON, this field is populated based on the HTTP body,
// because of the `body: "book"` syntax.
Book book = 2 [(google.api.field_behavior) = REQUIRED];
// The user-specified ID for the book.
// When using HTTP/JSON, this field is populated based on a query string
// argument, such as `?bookId=foo`. This is the fallback for fields that
// are not included in either the URI or the body.
// Note that clients use camelCase format to communicate the field names
// to the service.
string book_id = 3;
}
- The first key (
post
in this example) corresponds to the HTTP method. RPCs may useget
,post
,patch
, ordelete
. - The corresponding value represents the URI.
- URIs must use the
{foo=bar/*}
syntax to represent a variable that should be populated in the request proto. When extracting a resource name, the variable must include the entire resource name, not just the ID component. - URIs may use nested fields for their variable names. (Additionally,
AIP-134 mandates this for
Update
requests.) - URIs must use the
*
character to represent ID components, which matches all URI-safe characters except for/
. URIs may use**
as the final segment of a URI if matching/
is required.
- URIs must use the
- The
body
key defines which single top-level field in the request will be sent as the HTTP body. If the body is*
, then this indicates that the request object itself is the HTTP body. The request body is encoded as JSON as defined by protocol buffers' canonical JSON encoding.- RPCs must not define a
body
at all for RPCs that use theGET
orDELETE
HTTP verbs. - RPCs must use the prescribed
body
for Create (AIP-133) and Update (AIP-134) requests. - RPCs should use the prescribed
body
for custom methods (AIP-136). - The
body
must not contain a nested field (or use the.
character), - The
body
must not be the same as a URI parameter. - The
body
must not be arepeated
field. - Fields should not use the
json_name
annotation to alter the field name in JSON, unless doing so for backwards-compatibility reasons.
- RPCs must not define a
Note: Bi-directional streaming RPCs should not include a google.api.http
annotation at all. If feasible, the service should provide non-streaming
equivalent RPCs.
Multiple URI bindings
Occasionally, an RPC needs to correspond to more than one URI:
rpc CreateBook(CreateBookRequest) returns (Book) {
option (google.api.http) = {
post: "/v1/{parent=publishers/*}/books"
body: "book"
additional_bindings: {
post: "/v1/{parent=authors/*}/books"
body: "book"
}
additional_bindings: {
post: "/v1/books"
body: "book"
}
};
}
- RPCs may define any number of additional bindings. The structure is
identical to the
google.api.http
annotation (in fact, it is a recursive reference). - RPCs must not define an additional binding within an additional binding.
- The
body
clause must be identical in the top-level annotation and each additional binding.
Changelog
- 2022-08-18: Added the comment that query string parameter names are in camelCase.
- 2021-01-06: Added clarification around
body
and nested fields. - 2019-09-23: Added a statement about request body encoding, and guidance
discouraging
json_name
.