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 suffix LongRunning may be used for this purpose. For example, to create a long-running book creation RPC (if the standard CreateBook method was designed before long-running aspects were considered), a custom CreateBookLongRunning method could be introduced.
  • The HTTP method must be GET or POST:
    • 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.
  • The body clause in the google.api.http annotation should be "*".
  • 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 to text: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.