AIP-136
Custom methods
Resource-oriented design (AIP-121) uses custom methods to provide a means to express arbitrary actions that are difficult to model using only the standard methods. Custom methods are important because they provide a means for an API's vocabulary to adhere to user intent.
Guidance
Custom methods should only be used for functionality that can not be easily expressed via standard methods; prefer standard methods if possible, due to their consistent semantics. (Of course, this only applies if the functionality in question actually conforms to the normal semantics; it is not a good idea to contort things to endeavor to make the standard methods "sort of work".)
While custom methods vary widely in how they are designed, many principles apply consistently:
// Archives the given book.
rpc ArchiveBook(ArchiveBookRequest) returns (ArchiveBookResponse) {
option (google.api.http) = {
post: "/v1/{name=publishers/*/books/*}:archive"
body: "*"
};
}
Note: The pattern above shows a custom method that operates on a specific resource. Custom methods can be associated with resources, collections, or services. The bullets below apply in all three cases.
- The name of the method should be a verb followed by a noun.
- The name must not contain prepositions ("for", "with", etc.).
- The verb in the name should not contain any of the standard method verbs (Get, List, Create, Update, Delete).
- The name must not include the term
Async
. Instead, if the intention is to differentiate between immediate and long-running RPCs, the suffixLongRunning
may be used for this purpose. For example, to create a long-running book creation RPC (if the standardCreateBook
method was designed before long-running aspects were considered), a customCreateBookLongRunning
method could be introduced.
- The HTTP method must be
GET
orPOST
:GET
must be used for methods retrieving data or resource state.POST
must be used if the method has side effects or mutates resources or data.
- The HTTP URI must use a
:
character followed by the custom verb (:archive
in the above example), and the verb in the URI must match the verb in the name of the RPC.- If word separation is required,
camelCase
must be used.
- If word separation is required,
- The
body
clause in thegoogle.api.http
annotation should be"*"
.- See HTTP and gRPC Transcoding for more information.
- Custom methods should take a request message matching the RPC
name, with a
Request
suffix. - Custom methods should return a response message matching the RPC
name, with a
Response
suffix.- When operating on a specific resource, a custom method may return the resource itself.
Resource-based custom methods
Custom methods must operate on a resource if the API can be modeled as such:
// Archives the given book.
rpc ArchiveBook(ArchiveBookRequest) returns (ArchiveBookResponse) {
option (google.api.http) = {
post: "/v1/{name=publishers/*/books/*}:archive"
body: "*"
};
}
- The parameter for the resource's name must be called
name
, and be the only variable in the URI path.
Collection-based custom methods
While most custom methods operate on a single resource, some custom methods may operate on a collection instead:
// Sorts the books from this publisher.
rpc SortBooks(SortBooksRequest) returns (SortBooksResponse) {
option (google.api.http) = {
post: "/v1/{parent=publishers/*}/books:sort"
body: "*"
};
}
- The collection's parent resource must be called
parent
, and be the only variable in the URI path. - The collection key (
books
in the above example) must be literal.
Stateless methods
Some custom methods are not attached to resources at all. These methods are generally stateless: they accept a request and return a response, and have no permanent effect on data within the API.
// Translates the provided text from one language to another.
rpc TranslateText(TranslateTextRequest) returns (TranslateTextResponse) {
option (google.api.http) = {
post: "/v1/{project=projects/*}:translateText"
body: "*"
};
}
- If the method runs in a particular scope (such as a project, as in the above
example), the field name in the request message should be the name of the
scope resource. If word separators are necessary,
snake_case
must be used. - The URI should place both the verb and noun after the
:
separator (avoid a "faux collection key" in the URI in this case, as there is no collection). For example,:translateText
is preferable totext:translate
. - Stateless methods must use
POST
if they involve billing.
Declarative-friendly resources
Declarative-friendly resources usually should not employ custom methods (except specific declarative-friendly custom methods discussed in other AIPs), because declarative-friendly tools are unable to automatically determine what to do with them.
An exception to this is for rarely-used, fundamentally imperative operations,
such as a Move
or Rename
operation, for which there would not be an
expectation of declarative support.
Rationale
HTTP path
Similar to standard methods, a custom method that operates on a resource or
collection needs a name
or parent
parameter to indicate the resource that it
operates on. This convention allows clients to map custom methods to the
appropriate resource.
HTTP methods
Allowing both GET
and POST
HTTP verbs allows a clear distinction for
which methods do not mutate data, and which ones do. Methods that only
read data have first-class concepts in some clients (DataSources in
Terraform) and clearly indicate to a user which methods can be called
without risk of runtime impact.
RPC name
The term "async" is commonly used in programming languages to indicate whether a specific method call is synchronous or asynchronous, including for making RPCs. That sync/async aspect is at a different abstraction level to whether the RPC itself is intended to start a long-running operation. Using "async" within the RPC name itself causes confusion, and can even cause issues for client libraries which generate both synchronous and asynchronous methods to call the RPC in some languages.
Changelog
- 2023-11-16: Included link to AIP-127 "HTTP and gRPC Transcoding" for guidance on body definition.
- 2023-05-16: Added prohibition of the term "async" within RPC names.
- 2023-05-09: Adding guidance for POST and GET, require parent instead of the resource singular.
- 2023-03-02: Explicitly discourage use of standard method verbs.
- 2022-06-02: Changed suffix descriptions to eliminate superfluous "-".
- 2020-10-06: Added declarative-friendly guidance.
- 2019-08-01: Changed the examples from "shelves" to "publishers", to present a better example of resource ownership.