HTTP and gRPC Transcoding
Number127
Permalinkgoogle.aip.dev/127
StateApproved
Created2019-08-22
Updated2019-08-22
Contents

AIP-127

HTTP and gRPC Transcoding

APIs that followresource-oriented design are defined usingRPCs, but the resource-oriented design framework allows them to also bepresented as APIs that largely follow REST/JSON conventions. This is importantin order to help developers use their existing knowledge: over 80% of thepublic APIs available follow most REST conventions, and developers areaccustomed to that pattern.

Guidance

APIsmust provide HTTP definitions for each RPC that they define, exceptfor bi-directional streaming RPCs, which can not be natively supported usingHTTP/1.1. When providing a bi-directional streaming method, an APIshouldalso offer an alternative method that does not rely on bi-directionalstreaming.

HTTP method and path

When using protocol buffers, each RPCmust define the HTTP method and pathusing thegoogle.api.http annotation:

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 (post in this example) corresponds to the HTTP method. RPCsmay useget,post,patch, ordelete.
    • RPCsmust use the prescribed HTTP verb for each standard method, as discussed inAIP-131,AIP-132,AIP-133,AIP-134, andAIP-135
    • RPCsshould use the prescribed HTTP verb for custom methods, as discussed inAIP-136.
    • RPCsshould not useput orcustom.
  • The corresponding value represents the URI.
    • URIsmust use the{foo=bar/*} syntax to represent a variable that should be populated in the request proto. When extracting aresource name, the variablemust include the entire resource name, not just the ID component.
    • URIsmay use nested fields for their variable names. (Additionally,AIP-134 mandates this forUpdate requests.)
    • URIsmust use the* character to represent ID components, which matches all URI-safe characters except for/. URIsmay use** as the final segment of a URI if matching/ is required.
  • Thebody 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' canonicalJSON encoding.
    • RPCsmust not define abody at all for RPCs that use theGET orDELETE HTTP verbs.
    • RPCsmust use the prescribedbody for Create (AIP-133) and Update (AIP-134) requests.
    • RPCsshould use the prescribedbody for custom methods (AIP-136).
    • Thebodymust not contain a nested field (or use the. character),
    • Thebodymust not be the same as a URI parameter.
    • Thebodymust not be arepeated field.
    • Fieldsshould not use thejson_name annotation to alter the field name in JSON, unless doing so for backwards-compatibility reasons.

Note: Bi-directional streaming RPCs should not include agoogle.api.httpannotation at all. If feasible, the serviceshould provide non-streamingequivalent 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"}};}
  • RPCsmay define any number of additional bindings. The structure is identical to thegoogle.api.http annotation (in fact, it is a recursive reference).
  • RPCsmust not define an additional binding within an additional binding.
  • Thebody clausemust 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 aroundbody and nested fields.
  • 2019-09-23: Added a statement about request body encoding, and guidance discouragingjson_name.