Skip to content

HTTP and gRPC Transcoding

APIs that follow [resource-oriented design][resources] 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

Protobuf 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.example.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 Get, List, Create, Update, and Delete
    • RPCs should use the prescribed HTTP verb for custom methods, as discussed in Custom Methods.
    • 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, AEP-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 (Create) and Update (AEP-134) requests.
    • RPCs should use the prescribed body for custom methods (Custom Methods).
    • 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.

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.