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 HTTP method for custom methods should usually be
POST
, unless the custom method maps more strongly to another HTTP verb.- Custom methods that serve as an alternative to get or list methods (such as
Search
) should useGET
. These methods must be idempotent and have no side effects. - Custom methods should not use
PATCH
orDELETE
.
- Custom methods that serve as an alternative to get or list methods (such as
- 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"*"
.- However, if using
GET
orDELETE
, thebody
clause must be absent.
- However, if using
- Custom methods should usually take a request message matching the RPC
name, with a
Request
suffix. - Custom methods should usually 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.
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/{publisher=publishers/*}/books:sort"
body: "*"
};
}
- If the collection has a parent, the field name in the request message
should be the target resource's singular noun (
publisher
in the above example). If word separators are necessary,snake_case
must be used. - 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.
Changelog
- 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.