AIP-127

HTTP and gRPC Transcoding

APIs that followresource-oriented designare 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

APIsmustprovide 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 APIshould also offer an alternative method that does not rely on bi-directional streaming.

HTTP method and path

When using protocol buffers, each RPCmustdefine the HTTP method and path using thegoogle.api.httpannotation:

rpcCreateBook(CreateBookRequest)returns(Book){
option(google.api.http)={
post:"/v1/{parent=publishers/*}/books"
body:"book"
};
}

messageCreateBookRequest{
// 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.
stringparent=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.
Bookbook=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.
stringbook_id=3;
}
  • The first key (postin this example) corresponds to the HTTP method. RPCs mayuseget,post,patch,ordelete.
    • RPCsmustuse the prescribed HTTP verb for each standard method, as discussed inAIP-131,AIP-132,AIP-133,AIP-134,and AIP-135
    • RPCsshoulduse the prescribed HTTP verb for custom methods, as discussed inAIP-136.
    • RPCsshould notuseputorcustom.
  • The corresponding value represents the URI.
    • URIsmustuse the{foo=bar/*}syntax to represent a variable that should be populated in the request proto. When extracting aresource name,the variablemustinclude the entire resource name, not just the ID component.
    • URIsmayuse nested fields for their variable names. (Additionally, AIP-134mandates this forUpdaterequests.)
    • URIsmustuse the*character to represent ID components, which matches all URI-safe characters except for/.URIsmayuse**as the final segment of a URI if matching/is required.
  • Thebodykey 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' canonicalJSON encoding.
    • RPCsmust notdefine abodyat all for RPCs that use theGETor DELETEHTTP verbs.
    • RPCsmustuse the prescribedbodyfor Create (AIP-133) and Update (AIP-134) requests.
    • RPCsshoulduse the prescribedbodyfor custom methods (AIP-136).
    • Thebodymust notcontain a nested field (or use the.character),
    • Thebodymust notbe the same as a URI parameter.
    • Thebodymust notbe arepeatedfield.
    • Fieldsshould notuse thejson_nameannotation to alter the field name in JSON, unless doing so for backwards-compatibility reasons.

Note:Bi-directional streaming RPCs should not include agoogle.api.http annotation at all. If feasible, the serviceshouldprovide non-streaming equivalent RPCs.

Multiple URI bindings

Occasionally, an RPC needs to correspond to more than one URI:

rpcCreateBook(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"
}
};
}
  • RPCsmaydefine any number of additional bindings. The structure is identical to thegoogle.api.httpannotation (in fact, it is a recursive reference).
  • RPCsmust notdefine an additional binding within an additional binding.
  • Thebodyclausemustbe 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 aroundbodyand nested fields.
  • 2019-09-23:Added a statement about request body encoding, and guidance discouragingjson_name.