Métodos padrão

Neste capítulo, definimos o conceito de métodos padrão, que são List, Get, Create, Update e Delete. Os métodos padrão reduzem a complexidade e aumentam a consistência. Mais de 70% dos métodos da API no repositório de APIs do Google são métodos padrão, o que os torna muito mais fáceis de aprender e usar.

Na tabela a seguir descrevemos como mapear métodos padrão para métodos HTTP:

Método padrão Mapeamento de HTTP Corpo de solicitação HTTP Corpo de resposta HTTP
List GET <collection URL> N/D Lista de recursos*
Get GET <resource URL> N/D Recurso*
Create POST <collection URL> Recurso Recurso*
Update PUT or PATCH <resource URL> Recurso Recurso*
Delete DELETE <resource URL> N/D google.protobuf.Empty**

*O recurso retornado dos métodos List, Get, Create e Update pode conter dados parciais se os métodos forem compatíveis com máscaras de campo de resposta que especificam um subconjunto de campos a serem retornados. Em alguns casos, a plataforma da API é compatível de modo nativo com máscaras de campo para todos os métodos.

**A resposta retornada por um método Delete em que o recurso não é removido imediatamente, como a atualização de uma sinalização ou a criação de uma operação de exclusão de longa duração, precisa conter a operação de longa duração ou o recurso modificado.

Em um método padrão, uma operação de longa duração também pode ser retornada para solicitações que não se completem no intervalo de tempo de uma única chamada da API.

Nas seções a seguir, descrevemos cada um dos métodos padrão em detalhes. Os exemplos mostram os métodos definidos em arquivos .proto com anotações especiais para os mapeamentos HTTP. Você pode encontrar muitos exemplos de uso de métodos padrão no repositório das APIs do Google.

List

O método List usa um nome de conjunto e zero ou mais parâmetros como entrada e retorna uma lista de recursos que combinam com a entrada.

O List é comumente usado para pesquisar recursos. O List é adequado para dados de um único conjunto que é delimitado em tamanho e não armazenado em cache. Para casos mais amplos, o método personalizado Search precisa ser usado.

Um lote "get", como um método em que vários códigos de recursos são usados e um objeto é retornado para cada um deles, precisa ser implementado como um método BatchGet personalizado em vez de List. No entanto, se você tem um método List existente com a mesma funcionalidade, é possível reutilizar o método List para esse propósito. Se você estiver usando um método BatchGet personalizado, ele precisa ser mapeado para HTTP GET.

Padrões comuns aplicáveis: paginação e ordenação de resultados.

Convenções de nomenclatura aplicáveis: campo de filtro e campo de resultados.

Mapeamento do HTTP:

  • No método List, é preciso usar um verbo GET do HTTP.
  • Os campos da mensagem de solicitação que recebem o nome do conjunto cujos recursos estão sendo listados devem mapear para o caminho do URL. Se o nome do conjunto é mapeado para o caminho do URL, o último segmento do modelo de URL (o código do conjunto) precisa ser literal.
  • Todos os campos restantes da mensagem de solicitação deverão ser mapeados para os parâmetros de consulta do URL.
  • Não há corpo da solicitação. A cláusula body não pode ser declarada na configuração da API.
  • O corpo de resposta deve conter uma lista de recursos junto com metadados opcionais.

Exemplo:

// Lists books in a shelf.
rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) {
  // List method maps to HTTP GET.
  option (google.api.http) = {
    // The `parent` captures the parent resource name, such as "shelves/shelf1".
    get: "/v1/{parent=shelves/*}/books"
  };
}

message ListBooksRequest {
  // The parent resource name, for example, "shelves/shelf1".
  string parent = 1;

  // The maximum number of items to return.
  int32 page_size = 2;

  // The next_page_token value returned from a previous List request, if any.
  string page_token = 3;
}

message ListBooksResponse {
  // The field name should match the noun "books" in the method name.  There
  // will be a maximum number of items returned based on the page_size field
  // in the request.
  repeated Book books = 1;

  // Token to retrieve the next page of results, or empty if there are no
  // more results in the list.
  string next_page_token = 2;
}

Get

O método Get usa um nome de recurso, zero ou mais parâmetros e retorna o recurso especificado.

Mapeamento do HTTP:

  • No método Get, é preciso usar um verbo GET do HTTP.
  • Os campos da mensagem de solicitação que recebem o nome do recurso precisam mapear para o caminho do URL.
  • Todos os campos restantes da mensagem de solicitação deverão ser mapeados para os parâmetros de consulta do URL.
  • Não há corpo da solicitação. A cláusula body não pode ser declarada na configuração da API.
  • O recurso retornado deverá mapear para todo o corpo de resposta.

Exemplo:

// Gets a book.
rpc GetBook(GetBookRequest) returns (Book) {
  // Get maps to HTTP GET. Resource name is mapped to the URL. No body.
  option (google.api.http) = {
    // Note the URL template variable which captures the multi-segment resource
    // name of the requested book, such as "shelves/shelf1/books/book2"
    get: "/v1/{name=shelves/*/books/*}"
  };
}

message GetBookRequest {
  // The field will contain name of the resource requested, for example:
  // "shelves/shelf1/books/book2"
  string name = 1;
}

Create

O método Create usa um nome de recurso pai, um recurso e zero ou mais parâmetros. Ele cria um novo recurso no recurso pai especificado e retorna o recurso recém-criado.

Se uma API é compatível com a criação de recursos, ela precisa ter um método Create para cada tipo de recurso que pode ser criado.

Mapeamento do HTTP:

  • No método Create, é preciso usar um verbo POST do HTTP.
  • A mensagem de solicitação precisa ter um campo parent que especifique o nome do recurso pai em que o recurso será criado.
  • O campo de mensagem de solicitação que contém o recurso precisa mapear para o corpo de solicitação. Se a anotação google.api.http for usada para o método Create, o body: "<resource_field>" precisa ser usado.
  • A solicitação pode conter um campo chamado <resource>_id para que os autores da chamada possam selecionar um código atribuído pelo cliente. Este campo pode estar dentro do recurso.
  • Todos os campos restantes da mensagem de solicitação deverão ser mapeados para os parâmetros de consulta do URL.
  • O recurso retornado deverá mapear para todo o corpo de resposta.

Se o método Create for compatível com o nome do recurso atribuído pelo cliente e o recurso já existir, a solicitação apresentará falha com o código do erro ALREADY_EXISTS ou usar outro nome de recurso atribuído pelo servidor. Além disso, será destacado na documentação que o nome do recurso criado pode ser diferente daquele que foi transmitido.

O método Create precisa ter um recurso de entrada para que, quando o esquema do recurso mudar, não seja necessário atualizar os esquemas de solicitação e de recursos. Os campos de recursos que não podem ser configurados pelos clientes precisam ser documentados como campos "Somente de saída".

Exemplo:

// Creates a book in a shelf.
rpc CreateBook(CreateBookRequest) returns (Book) {
  // Create maps to HTTP POST. URL path as the collection name.
  // HTTP request body contains the resource.
  option (google.api.http) = {
    // The `parent` captures the parent resource name, such as "shelves/1".
    post: "/v1/{parent=shelves/*}/books"
    body: "book"
  };
}

message CreateBookRequest {
  // The parent resource name where the book is to be created.
  string parent = 1;

  // The book id to use for this book.
  string book_id = 3;

  // The book resource to create.
  // The field name should match the Noun in the method name.
  Book book = 2;
}

rpc CreateShelf(CreateShelfRequest) returns (Shelf) {
  option (google.api.http) = {
    post: "/v1/shelves"
    body: "shelf"
  };
}

message CreateShelfRequest {
  Shelf shelf = 1;
}

Update

O método Update usa uma mensagem de solicitação que contém um recurso e zero ou mais parâmetros. Ele atualiza o recurso especificado e as respectivas propriedades e retorna o recurso atualizado.

As propriedades mutáveis do recurso precisam ser alteradas pelo método Update, exceto aquelas que contiverem o nome ou o pai do recurso. Funcionalidades para renomear ou mover um recurso não podem ser executadas no método Update. Em vez disso, precisam ser processadas por um método personalizado.

Mapeamento do HTTP:

  • O método Update padrão precisa ser compatível com a atualização parcial do recurso e usar o verbo PATCH do HTTP com um campo FieldMask chamado update_mask. Campos de saída que são fornecidos pelo cliente como entradas precisam ser ignorados.
  • Um método Update em que seja necessária uma semântica de patches mais avançada, como anexação a um campo repetido, precisa ser disponibilizado por um método personalizado.
  • Se o método Update for compatível apenas com a atualização completa do recurso, use o verbo PUT do HTTP. No entanto, a atualização completa não é recomendada, porque podem ocorrer problemas de compatibilidade com versões anteriores durante a adição de novos campos de recursos.
  • O campo de mensagem que recebe o nome do recurso precisa mapear para o caminho do URL. O campo pode estar na própria mensagem do recurso.
  • O campo de mensagem de solicitação que contém o recurso precisa mapear para o corpo de solicitação.
  • Todos os campos restantes da mensagem de solicitação precisam ser mapeados para os parâmetros da consulta do URL.
  • A mensagem de resposta precisa ser o próprio recurso atualizado.

Se a API aceitar nomes de recurso atribuídos pelo cliente, o servidor pode permitir que o cliente especifique um nome de recurso inexistente e crie um novo recurso. Caso contrário, o método Update apresentará falha com o nome do recurso inexistente. O código de erro NOT_FOUND precisa ser usado se ele for a única condição de erro.

É preciso usar também um método Create em uma API com método Update compatível com a criação de recursos. O motivo é que não está claro como se criam recursos se o método Update é a única maneira de fazer isso.

Exemplo:

// Updates a book.
rpc UpdateBook(UpdateBookRequest) returns (Book) {
  // Update maps to HTTP PATCH. Resource name is mapped to a URL path.
  // Resource is contained in the HTTP request body.
  option (google.api.http) = {
    // Note the URL template variable which captures the resource name of the
    // book to update.
    patch: "/v1/{book.name=shelves/*/books/*}"
    body: "book"
  };
}

message UpdateBookRequest {
  // The book resource which replaces the resource on the server.
  Book book = 1;

  // The update mask applies to the resource. For the `FieldMask` definition,
  // see https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#fieldmask
  FieldMask update_mask = 2;
}

Delete

O método Delete usa um nome de recurso e zero ou mais parâmetros, e exclui ou agende para exclusão o recurso especificado. O método Delete precisa retornar google.protobuf.Empty.

Uma API não pode depender de informações retornadas por um método Delete, já que não é possível invocá-lo repetidamente.

Mapeamento do HTTP:

  • No método Delete, é preciso usar um verbo DELETE do HTTP.
  • Os campos da mensagem de solicitação que recebem o nome do recurso precisam mapear para o caminho do URL.
  • Todos os campos restantes da mensagem de solicitação deverão ser mapeados para os parâmetros de consulta do URL.
  • Não há corpo da solicitação. A cláusula body não pode ser declarada na configuração da API.
  • Se o recurso for removido imediatamente pelo método Delete, uma resposta vazia precisará ser retornada.
  • Se uma operação de longa duração for iniciada pelo método Delete, ela precisará ser retornada.
  • Se o método Delete apenas marcar o recurso como excluído, o recurso atualizado precisará ser retornado.

As chamadas para o método Delete precisam ter efeito idempotente, mas não precisam gerar a mesma resposta. Qualquer número de solicitações Delete precisa resultar em um recurso excluído em algum momento, mas apenas a primeira solicitação precisa resultar em um código de sucesso. As solicitações subsequentes precisam resultar em google.rpc.Code.NOT_FOUND.

Exemplo:

// Deletes a book.
rpc DeleteBook(DeleteBookRequest) returns (google.protobuf.Empty) {
  // Delete maps to HTTP DELETE. Resource name maps to the URL path.
  // There is no request body.
  option (google.api.http) = {
    // Note the URL template variable capturing the multi-segment name of the
    // book resource to be deleted, such as "shelves/shelf1/books/book2"
    delete: "/v1/{name=shelves/*/books/*}"
  };
}

message DeleteBookRequest {
  // The resource name of the book to be deleted, for example:
  // "shelves/shelf1/books/book2"
  string name = 1;
}
Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…