| Custom methods | |
|---|---|
| Number | 136 |
| Permalink | google.aip.dev/136 |
| State | Approved |
| Created | 2019-01-25 |
| Updated | 2019-01-25 |
AIP-136
Custom methods
Resource-oriented design (AIP-121) uses custom methods to provide a means toexpress arbitrary actions that are difficult to model using only the standardmethods. Custom methods are important because they provide a means for an API'svocabulary to adhere to user intent.
Guidance
Custom methodsshould only be used for functionality that can not be easilyexpressed via standard methods; prefer standard methods if possible, due totheir consistent semantics. (Of course, this only applies if the functionalityin question actually conforms to the normal semantics; it isnot a good ideato contort things to endeavor to make the standard methods "sort of work".)
While custom methods vary widely in how they are designed, many principlesapply consistently:
// Archives the given book.rpcArchiveBook(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 specificresource. Custom methods can be associated with resources, collections, orservices. The bullets below apply in all three cases.
- The name of the methodshould be a verb followed by a noun.
- The namemust not contain prepositions ("for", "with", etc.).
- The verb in the nameshould not contain any of the standard method verbs (Get,List,Create,Update,Delete).
- The namemust not include the term
Async. Instead, if the intention is to differentiate between immediate and long-running RPCs, the suffixLongRunningmay be used for this purpose. For example, to create a long-running book creation RPC (if the standardCreateBookmethod was designed before long-running aspects were considered), a customCreateBookLongRunningmethod could be introduced.
- The HTTP methodmust be
GETorPOST:GETmust be used for methods retrieving data or resource state.POSTmust be used if the method has side effects or mutates resources or data.
- The HTTP URImust use a
:character followed by the custom verb (:archivein the above example), and the verb in the URImust match the verb in the name of the RPC.- If word separation is required,
camelCasemust be used.
- If word separation is required,
- The
bodyclause in thegoogle.api.httpannotationshould be"*".- SeeHTTP and gRPC Transcoding for more information.
- Custom methodsshould take a request message matching the RPC name, with a
Requestsuffix. - Custom methodsshould return a response message matching the RPC name, with a
Responsesuffix.- When operating on a specific resource, a custom methodmay return the resource itself.
Resource-based custom methods
Custom methodsmust operate on a resource if the API can be modeledas such:
// Archives the given book.rpcArchiveBook(ArchiveBookRequest)returns(ArchiveBookResponse){option(google.api.http)={post:"/v1/{name=publishers/*/books/*}:archive"body:"*"};}- The parameter for the resource's namemust 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 methodsmay operate on a collection instead:
// Sorts the books from this publisher.rpcSortBooks(SortBooksRequest)returns(SortBooksResponse){option(google.api.http)={post:"/v1/{parent=publishers/*}/books:sort"body:"*"};}- If the collection's resource has a parent, that resourcemust be called
parentand be the only variable in the URI path. - The collection key (
booksin the above example)must be literal.
Stateless methods
Some custom methods are not attached to resources at all. These methods aregenerallystateless: they accept a request and return a response, and have nopermanent effect on data within the API.
// Translates the provided text from one language to another.rpcTranslateText(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 messageshould be the name of the scope resource. If word separators are necessary,
snake_casemust be used. - The URIshould 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,:translateTextis preferable totext:translate. - Stateless methodsmust use
POSTif they involve billing.
Declarative-friendly resources
Declarative-friendly resources usuallyshould not employ custom methods(except specific declarative-friendly custom methods discussed in other AIPs),because declarative-friendly tools are unable to automatically determine whatto do with them.
An exception to this is for rarely-used, fundamentally imperative operations,such as aMove orRename operation, for which there would not be anexpectation of declarative support.
Rationale
HTTP path
Similar to standard methods, a custom method that operates on a resource orcollection needs aname orparent parameter to indicate the resource that itoperates on. This convention allows clients to map custom methods to theappropriate resource.
HTTP methods
Allowing bothGET andPOST HTTP verbs allows a clear distinction forwhich methods do not mutate data, and which ones do. Methods that onlyread data have first-class concepts in some clients (DataSources inTerraform) and clearly indicate to a user which methods can be calledwithout risk of runtime impact.
Disallowing prepositions
Generally, method names with prepositions indicate that a new method is beingused where a field should instead be added to an existing method, or the methodshould use a distinct verb. For example, if aCreateBook message alreadyexists and you are considering addingCreateBookFromDictation, consider aTranscribeBook method instead. Similarly, if there is desire for aproperty-specific look-up method, instead ofGetBookByAuthor consider aSearchBooks with anauthor field as a search dimension. This helps preventan explosion of hyper-focused methods that bloat API and client surfaces, andadd complexity to both managing and consuming the API.
RPC name
The term "async" is commonly used in programming languages to indicate whethera specific method call is synchronous or asynchronous, including for making RPCs.That sync/async aspect is at a different abstraction level to whether the RPCitself is intended to start a long-running operation. Using "async" within theRPC name itself causes confusion, and can even cause issues for client librarieswhich generate both synchronous and asynchronous methods to call the RPC in somelanguages.
Changelog
- 2025-05-12: Extend disallowing prepositions rationale.
- 2025-01-09: Add original rationale for disallowing prepositions in names.
- 2023-11-16: Included link toAIP-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.
View on GitHub