Custom methods
Number136
Permalinkgoogle.aip.dev/136
StateApproved
Created2019-01-25
Updated2019-01-25
Contents

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 termAsync. 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 standardCreateBook method was designed before long-running aspects were considered), a customCreateBookLongRunning method could be introduced.
  • The HTTP methodmust beGET orPOST:
    • 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 (:archive in 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.
  • Thebody clause in thegoogle.api.http annotationshould be"*".
  • Custom methodsshould take a request message matching the RPC name, with aRequest suffix.
  • Custom methodsshould return a response message matching the RPC name, with aResponse suffix.
    • 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 calledname, 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 calledparent 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 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,:translateText is preferable totext:translate.
  • Stateless methodsmust usePOST if 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.