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 use get, post, patch, or delete.
    • RPCs must use the prescribed HTTP verb for each standard method, as discussed in AIP-131, AIP-132, AIP-133, AIP-134, and AIP-135
    • RPCs should use the prescribed HTTP verb for custom methods, as discussed in AIP-136.
    • RPCs should not use put or custom.
  • 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.
  • 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 the GET or DELETE 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 a repeated field.
    • Fields should not use the json_name annotation to alter the field name in JSON, unless doing so for backwards-compatibility reasons.

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.