Design de API webWeb API design

Aplicativos Web mais modernos expõem APIs que os clientes podem usar para interagir com o aplicativo.Most modern web applications expose APIs that clients can use to interact with the application. Uma API da Web bem projetada deve buscar apoiar:A well-designed web API should aim to support:

  • Independência de plataforma.Platform independence. Qualquer cliente deve ser capaz de chamar a API, independentemente de como a API está implementada internamente.Any client should be able to call the API, regardless of how the API is implemented internally. Isso requer o uso de protocolos padrão e ter um mecanismo pelo qual o cliente e o serviço Web pode concordar com o formato dos dados a serem trocados.This requires using standard protocols, and having a mechanism whereby the client and the web service can agree on the format of the data to exchange.

  • Evolução do serviço.Service evolution. A API da Web deve ser capaz de evoluir e adicionar funcionalidade independentemente de aplicativos cliente.The web API should be able to evolve and add functionality independently from client applications. À medida que a API evolui, aplicativos cliente existentes devem continuar a funcionar sem modificação.As the API evolves, existing client applications should continue to function without modification. Todas as funcionalidades devem ser detectáveis para que os aplicativos cliente possam utilizá-las plenamente.All functionality should be discoverable so that client applications can fully use it.

Essas diretrizes descrevem questões que você deve considerar ao criar uma API da Web.This guidance describes issues that you should consider when designing a web API.

Introdução a RESTIntroduction to REST

Em 2000, Roy Fielding propôs a Transferência de Estado Representacional (REST) como uma abordagem de arquitetura para criar serviços Web.In 2000, Roy Fielding proposed Representational State Transfer (REST) as an architectural approach to designing web services. REST é um estilo arquitetural para a criação de sistemas distribuídos com base em hipermídia.REST is an architectural style for building distributed systems based on hypermedia. A REST é independente de qualquer protocolo subjacente e não está necessariamente ligada a HTTP.REST is independent of any underlying protocol and is not necessarily tied to HTTP. No entanto, as implementações mais comuns de REST usam HTTP como o protocolo de aplicativo, e este guia foca a criação de APIs REST para HTTP.However, most common REST implementations use HTTP as the application protocol, and this guide focuses on designing REST APIs for HTTP.

Uma vantagem principal do REST sobre HTTP é que ele usa padrões abertos e não vincula a implementação da API ou os aplicativos cliente a nenhuma implementação específica.A primary advantage of REST over HTTP is that it uses open standards, and does not bind the implementation of the API or the client applications to any specific implementation. Por exemplo, um serviço Web REST poderia ser escrito em ASP.NET, e aplicativos cliente podem usar qualquer linguagem ou o conjunto de ferramentas que possa gerar solicitações HTTP e analisar respostas HTTP.For example, a REST web service could be written in ASP.NET, and client applications can use any language or toolset that can generate HTTP requests and parse HTTP responses.

Aqui estão alguns dos princípios de design mais importante de APIs RESTful usando HTTP:Here are some of the main design principles of RESTful APIs using HTTP:

  • APIs REST são projetadas para recursos, que se tratam de qualquer tipo de objeto, dados ou serviço que possa ser acessado pelo cliente.REST APIs are designed around resources, which are any kind of object, data, or service that can be accessed by the client.

  • Um recurso tem um identificador, o qual se trata de um URI que identifica exclusivamente esse recurso.A resource has an identifier, which is a URI that uniquely identifies that resource. Por exemplo, o URI para um pedido determinada do cliente pode ser:For example, the URI for a particular customer order might be:

    https://adventure-works.com/orders/1
    
  • Os clientes interagem com um serviço por meio da troca de representações de recursos.Clients interact with a service by exchanging representations of resources. Muitas APIs da Web usam JSON como o formato de troca.Many web APIs use JSON as the exchange format. Por exemplo, uma solicitação GET para o URI listado acima poderia retornar este corpo de resposta:For example, a GET request to the URI listed above might return this response body:

    {"orderId":1,"orderValue":99.90,"productId":1,"quantity":1}
    
  • As APIs REST usam uma interface uniforme, o que ajuda a separar as implementações de cliente e de serviço.REST APIs use a uniform interface, which helps to decouple the client and service implementations. Para APIs REST baseadas em HTTP, a interface uniforme inclui o uso de verbos HTTP padrão para executar operações em recursos.For REST APIs built on HTTP, the uniform interface includes using standard HTTP verbs to perform operations on resources. As operações mais comuns são GET, POST, PUT, PATCH e DELETE.The most common operations are GET, POST, PUT, PATCH, and DELETE.

  • As APIs REST usam um modelo de solicitação sem estado.REST APIs use a stateless request model. Solicitações HTTP devem ser independentes e podem ocorrer em qualquer pedido, portanto, não é viável manter informações de estado transitório entre as solicitações.HTTP requests should be independent and may occur in any order, so keeping transient state information between requests is not feasible. O único local onde as informações são armazenadas é nos próprios recursos, e cada solicitação deve ser uma operação atômica.The only place where information is stored is in the resources themselves, and each request should be an atomic operation. Essa restrição permite que serviços Web sejam altamente dimensionáveis porque não é necessário manter nenhum tipo de afinidade entre clientes e servidores específicos.This constraint enables web services to be highly scalable, because there is no need to retain any affinity between clients and specific servers. Todos os servidores podem tratar de solicitações de qualquer cliente.Any server can handle any request from any client. Dito isso, outros fatores podem limitar a escalabilidade.That said, other factors can limit scalability. Por exemplo, muitos serviços web escrevem em um armazenamento de dados backend, o que pode ser difícil de dimensionar. Para obter mais informações sobre estratégias para dimensionar um armazenamento de dados, consulte particionamento de dados horizontal, vertical e funcional.For example, many web services write to a backend data store, which may be hard to scale out. For more information about strategies to scale out a data store, see Horizontal, vertical, and functional data partitioning.

  • As APIs REST são orientadas por links de hipermídia contidos na representação.REST APIs are driven by hypermedia links that are contained in the representation. Por exemplo, a seguir é mostrada uma representação JSON de um pedido.For example, the following shows a JSON representation of an order. Ela contém links para obter ou atualizar o cliente associado ao pedido.It contains links to get or update the customer associated with the order.

    {
        "orderID":3,
        "productID":2,
        "quantity":4,
        "orderValue":16.60,
        "links": [
            {"rel":"product","href":"https://adventure-works.com/customers/3", "action":"GET" },
            {"rel":"product","href":"https://adventure-works.com/customers/3", "action":"PUT" }
        ]
    }
    

Em 2008, Leonard Richardson propôs seguintes modelo de maturidade para APIs da Web:In 2008, Leonard Richardson proposed the following maturity model for web APIs:

  • Nível 0: defina um URI, e todas as operações são solicitações POST para esse URI.Level 0: Define one URI, and all operations are POST requests to this URI.
  • Nível 1: crie URIs separados para recursos individuais.Level 1: Create separate URIs for individual resources.
  • Nível 2: use métodos HTTP para definir as operações nos recursos.Level 2: Use HTTP methods to define operations on resources.
  • Nível 3: use hipermídia (HATEOAS, descrita abaixo).Level 3: Use hypermedia (HATEOAS, described below).

O Nível 3 corresponde a uma API RESTful de verdade de acordo com a definição de Fielding.Level 3 corresponds to a truly RESTful API according to Fielding's definition. Na prática, muitas APIs da Web publicadas se enquadram em algum lugar do Nível 2.In practice, many published web APIs fall somewhere around level 2.

Organizar a API em torno de recursosOrganize the API around resources

Concentre-se nas entidades comerciais que a API da Web expõe.Focus on the business entities that the web API exposes. Por exemplo, em um sistema de comércio eletrônico, as entidades primárias podem ser clientes e pedidos.For example, in an e-commerce system, the primary entities might be customers and orders. É possível criar um pedido por meio do envio de uma solicitação HTTP POST que contenha as informações do pedido.Creating an order can be achieved by sending an HTTP POST request that contains the order information. A resposta HTTP indica se o pedido foi feito com êxito ou não.The HTTP response indicates whether the order was placed successfully or not. Quando possível, os URIs de recursos devem ser baseados em substantivos (o recurso) e não em verbos (as operações no recurso).When possible, resource URIs should be based on nouns (the resource) and not verbs (the operations on the resource).

https://adventure-works.com/orders // Good

https://adventure-works.com/create-order // Avoid

Um recurso não precisa ser baseado em um único item de dados físicos.A resource doesn't have to be based on a single physical data item. Por exemplo, um recurso de pedido pode ser implementado internamente como várias tabelas em um banco de dados relacional, mas apresentado ao cliente como uma única entidade.For example, an order resource might be implemented internally as several tables in a relational database, but presented to the client as a single entity. Evite criar APIs que simplesmente espelhem a estrutura interna de um banco de dados.Avoid creating APIs that simply mirror the internal structure of a database. A finalidade da REST é modelar entidades e as operações que um aplicativo pode executar nessas entidades.The purpose of REST is to model entities and the operations that an application can perform on those entities. Um cliente não deve ser exposto à implementação interna.A client should not be exposed to the internal implementation.

Entidades geralmente são agrupadas em coleções (pedidos, clientes).Entities are often grouped together into collections (orders, customers). Uma coleção é um recurso separado do item na coleção e deve ter seu próprio URI.A collection is a separate resource from the item within the collection, and should have its own URI. Por exemplo, o seguinte URI pode representar a coleção de pedidos:For example, the following URI might represent the collection of orders:

https://adventure-works.com/orders

O envio de uma solicitação HTTP GET para o URI da coleção recupera uma lista de itens na coleção.Sending an HTTP GET request to the collection URI retrieves a list of items in the collection. Cada item na coleção também tem seu próprio URI exclusivo.Each item in the collection also has its own unique URI. Uma solicitação HTTP GET para o URI do item retorna os detalhes desse item.An HTTP GET request to the item's URI returns the details of that item.

Adote uma convenção de nomenclatura consistente nos URIs.Adopt a consistent naming convention in URIs. Em geral, é bom usar substantivos plurais para URIs que fazem referência a coleções.In general, it helps to use plural nouns for URIs that reference collections. É uma boa prática organizar URIs de coleções e itens em uma hierarquia.It's a good practice to organize URIs for collections and items into a hierarchy. Por exemplo, /customers é o caminho para a coleção de clientes, e /customers/5 é o caminho para o cliente com a ID igual a 5.For example, /customers is the path to the customers collection, and /customers/5 is the path to the customer with ID equal to 5. Essa abordagem ajuda a manter a API da Web intuitiva.This approach helps to keep the web API intuitive. Além disso, muitas estruturas de API da Web podem rotear solicitações baseadas em caminhos de URI com parâmetros, de modo que é possível definir uma rota para o caminho /customers/{id}.Also, many web API frameworks can route requests based on parameterized URI paths, so you could define a route for the path /customers/{id}.

Também considere as relações entre diferentes tipos de recursos e como você pode expor essas associações.Also consider the relationships between different types of resources and how you might expose these associations. Por exemplo, /customers/5/orders pode representar todos os pedidos do cliente 5.For example, the /customers/5/orders might represent all of the orders for customer 5. Também é possível ir na outra direção e representar a associação de um pedido de volta a um cliente com um URI como /orders/99/customer.You could also go in the other direction, and represent the association from an order back to a customer with a URI such as /orders/99/customer. No entanto, estender esse modelo demasiadamente pode torná-lo difícil de ser implementado.However, extending this model too far can become cumbersome to implement. Uma solução melhor é fornecer links navegáveis para recursos associados no corpo da mensagem de resposta HTTP.A better solution is to provide navigable links to associated resources in the body of the HTTP response message. Este mecanismo é descrito com mais detalhes na seção Use HATEOAS para permitir a navegação a recursos relacionados.This mechanism is described in more detail in the section Use HATEOAS to enable navigation to related resources.

Em sistemas mais complexos, pode ser tentador fornecer URIs que permitam que um cliente navegue entre vários níveis de relações, como /customers/1/orders/99/products.In more complex systems, it can be tempting to provide URIs that enable a client to navigate through several levels of relationships, such as /customers/1/orders/99/products. No entanto, esse nível de complexidade pode ser difícil de manter e é inflexível no caso de as relações entre os recursos mudarem no futuro.However, this level of complexity can be difficult to maintain and is inflexible if the relationships between resources change in the future. Em vez disso, tente manter os URIs relativamente simples.Instead, try to keep URIs relatively simple. Uma vez que um aplicativo tem uma referência a um recurso, deve ser possível usar essa referência para localizar itens relacionados a esse recurso.Once an application has a reference to a resource, it should be possible to use this reference to find items related to that resource. A consulta anterior pode ser substituída com o URI /customers/1/orders para localizar todos os pedidos do cliente 1 e depois /orders/99/products para localizar os produtos nesse pedido.The preceding query can be replaced with the URI /customers/1/orders to find all the orders for customer 1, and then /orders/99/products to find the products in this order.

Dica

Evite exigir URIs de recurso mais complexos do que collection/item/collection.Avoid requiring resource URIs more complex than collection/item/collection.

Outro fator é que todas as solicitações Web impõem uma carga no servidor Web.Another factor is that all web requests impose a load on the web server. Quanto mais solicitações, maior a carga.The more requests, the bigger the load. Portanto, tente evitar APIs da Web "verborrágicas" que expõem um grande número de recursos pequenos.Therefore, try to avoid "chatty" web APIs that expose a large number of small resources. Uma API desse tipo pode exigir que um aplicativo cliente envie várias solicitações para localizar todos os dados de que ele precisa.Such an API may require a client application to send multiple requests to find all of the data that it requires. Em vez disso, talvez você deseje desnormalizar os dados e combinar informações relacionadas em recursos maiores, que podem ser recuperados com uma única solicitação.Instead, you might want to denormalize the data and combine related information into bigger resources that can be retrieved with a single request. No entanto, você precisa equilibrar essa abordagem em relação à sobrecarga causada pela busca de dados de que o cliente não precisa.However, you need to balance this approach against the overhead of fetching data that the client doesn't need. Recuperar objetos grandes pode aumentar a latência de uma solicitação e incorrer em custos adicionais de largura de banda.Retrieving large objects can increase the latency of a request and incur additional bandwidth costs. Para obter mais informações sobre esses antipadrões de desempenho, consulte E/S verborrágica e Busca estranha.For more information about these performance antipatterns, see Chatty I/O and Extraneous Fetching.

Evite introduzir as dependências entre a API da Web e as fontes de dados subjacentes.Avoid introducing dependencies between the web API and the underlying data sources. Por exemplo, se seus dados estão armazenados em um banco de dados relacional, a API da Web não precisa expor cada tabela como uma coleção de recursos.For example, if your data is stored in a relational database, the web API doesn't need to expose each table as a collection of resources. Na verdade, provavelmente esse seja um design ruim.In fact, that's probably a poor design. Em vez disso, pense na API da Web como uma abstração do banco de dados.Instead, think of the web API as an abstraction of the database. Se necessário, introduza uma camada de mapeamento entre o banco de dados e a API da Web.If necessary, introduce a mapping layer between the database and the web API. Dessa forma, os aplicativos cliente ficam isolados das alterações do esquema de banco de dados subjacente.That way, client applications are isolated from changes to the underlying database scheme.

Por fim, pode não ser possível mapear toda operação implementada por uma API da Web para um recurso específico.Finally, it might not be possible to map every operation implemented by a web API to a specific resource. Você pode tratar desses cenários sem recursos por meio de solicitações HTTP, que invocam uma função e retornam os resultados como uma mensagem de resposta HTTP.You can handle such non-resource scenarios through HTTP requests that invoke a function and return the results as an HTTP response message. Por exemplo, uma API da Web que implementa operações simples de calculadora, como adicionar e subtrair, pode fornecer URIs que exponham essas operações como pseudorrecursos, além de utilizar a cadeia de consulta para especificar os parâmetros necessários.For example, a web API that implements simple calculator operations such as add and subtract could provide URIs that expose these operations as pseudo resources and use the query string to specify the parameters required. Por exemplo, uma solicitação GET para o URI /add?operand1=99&operand2=1 retornaria uma mensagem de resposta com o corpo contendo o valor 100.For example, a GET request to the URI /add?operand1=99&operand2=1 would return a response message with the body containing the value 100. No entanto, use essas formas de URIs apenas com moderação.However, only use these forms of URIs sparingly.

Definir operações em termos de métodos HTTPDefine operations in terms of HTTP methods

O protocolo HTTP define vários métodos que atribuem significado semântico a uma solicitação.The HTTP protocol defines a number of methods that assign semantic meaning to a request. Os métodos HTTP comuns usados pelas APIs da Web mais RESTful são:The common HTTP methods used by most RESTful web APIs are:

  • GET, que recupera uma representação do recurso no URI especificado.GET retrieves a representation of the resource at the specified URI. O corpo da mensagem de resposta contém os detalhes do recurso solicitado.The body of the response message contains the details of the requested resource.
  • POST, que cria um novo recurso no URI especificado.POST creates a new resource at the specified URI. O corpo da mensagem de solicitação fornece os detalhes do novo recurso.The body of the request message provides the details of the new resource. Observe que POST também pode ser usado para disparar operações que, na verdade, não criam recursos.Note that POST can also be used to trigger operations that don't actually create resources.
  • PUT, que cria ou substitui o recurso no URI especificado.PUT either creates or replaces the resource at the specified URI. O corpo da mensagem de solicitação especifica o recurso a ser criado ou atualizado.The body of the request message specifies the resource to be created or updated.
  • PATCH, que realiza uma atualização parcial de um recurso.PATCH performs a partial update of a resource. O corpo da solicitação especifica o conjunto de alterações a ser aplicado ao recurso.The request body specifies the set of changes to apply to the resource.
  • DELETE, que remove o recurso do URI especificado.DELETE removes the resource at the specified URI.

O efeito de uma solicitação específica deve depender de o recurso ser uma coleção ou um item individual.The effect of a specific request should depend on whether the resource is a collection or an individual item. A tabela a seguir resume as convenções comuns adotadas pela maioria das implementações RESTful usando o exemplo de e-commerce.The following table summarizes the common conventions adopted by most RESTful implementations using the e-commerce example. Nem todas essas solicitações—podem ser implementadas, depende do cenário específico.Not all of these requests might be implemented—it depends on the specific scenario.

RecursoResource POSTPOST ObterGET ColocarPUT ExcluirDELETE
/clientes/customers Criar um novo clienteCreate a new customer Obter todos os clientesRetrieve all customers Atualização em massa de clientesBulk update of customers Remover todos os clientesRemove all customers
/clientes/1/customers/1 ErroError Obter os detalhes do cliente 1Retrieve the details for customer 1 Atualizar os detalhes do cliente 1 se ele existirUpdate the details of customer 1 if it exists Remover cliente 1Remove customer 1
/clientes/1/pedidos/customers/1/orders Criar um novo pedido para o cliente 1Create a new order for customer 1 Obter todos os pedidos do cliente 1Retrieve all orders for customer 1 Atualização em massa de pedidos do cliente 1Bulk update of orders for customer 1 Remover todos os pedidos do cliente 1Remove all orders for customer 1

As diferenças entre POST, PUT e PATCH podem ser confusas.The differences between POST, PUT, and PATCH can be confusing.

  • Uma solicitação POST cria um recurso.A POST request creates a resource. O servidor atribui um URI para o novo recurso e retorna esse URI para o cliente.The server assigns a URI for the new resource, and returns that URI to the client. No modelo de REST, você frequentemente aplica solicitações POST para coleções.In the REST model, you frequently apply POST requests to collections. O novo recurso é adicionado à coleção.The new resource is added to the collection. Uma solicitação POST também pode ser usada para enviar dados para o processamento de um recurso existente sem que nenhum novo recurso seja criado.A POST request can also be used to submit data for processing to an existing resource, without any new resource being created.

  • Uma solicitação PUT cria um recurso ou atualiza um recurso existente.A PUT request creates a resource or updates an existing resource. O cliente especifica o URI do recurso.The client specifies the URI for the resource. O corpo da solicitação contém uma representação completa do recurso.The request body contains a complete representation of the resource. Se já existir um recurso com esse URI, ele será substituído.If a resource with this URI already exists, it is replaced. Caso contrário, um novo recurso é criado, caso o servidor ofereça suporte a isso.Otherwise a new resource is created, if the server supports doing so. Solicitações PUT são aplicadas mais frequentemente a recursos que sejam itens individuais, como um cliente específico, em vez de coleções.PUT requests are most frequently applied to resources that are individual items, such as a specific customer, rather than collections. Um servidor pode oferecer suporte a atualizações, mas não a uma criação por meio de PUT.A server might support updates but not creation via PUT. O suporte à criação por meio de PUT depende de se o cliente pode atribuir significativamente um URI a um recurso antes que ele exista.Whether to support creation via PUT depends on whether the client can meaningfully assign a URI to a resource before it exists. Se não, use o POST para criar recursos e o PUT ou o PATCH para atualizar.If not, then use POST to create resources and PUT or PATCH to update.

  • Uma solicitação PATCH executa uma atualização parcial a um recurso existente.A PATCH request performs a partial update to an existing resource. O cliente especifica o URI do recurso.The client specifies the URI for the resource. O corpo da solicitação especifica um conjunto de alterações a ser aplicado ao recurso.The request body specifies a set of changes to apply to the resource. Isso pode ser mais eficiente do que usar o PUT, porque o cliente envia apenas as alterações, e não a representação inteira do recurso.This can be more efficient than using PUT, because the client only sends the changes, not the entire representation of the resource. Tecnicamente, o PATCH também pode criar um novo recurso (especificando um conjunto de atualizações para um recurso "null"), se o servidor oferecer suporte a isso.Technically PATCH can also create a new resource (by specifying a set of updates to a "null" resource), if the server supports this.

Solicitações PUT devem ser idempotentes.PUT requests must be idempotent. Se um cliente enviar a mesma solicitação PUT várias vezes, os resultados deverão ser sempre os mesmos (o mesmo recurso será modificado com os mesmos valores).If a client submits the same PUT request multiple times, the results should always be the same (the same resource will be modified with the same values). Não há garantia de que as solicitações POST e PATCH sejam idempotentes.POST and PATCH requests are not guaranteed to be idempotent.

Em conformidade com a semântica HTTPConform to HTTP semantics

Esta seção descreve algumas considerações comuns para a criação de uma API que esteja em conformidade com a especificação de HTTP.This section describes some typical considerations for designing an API that conforms to the HTTP specification. No entanto, não serão abordados todos os detalhes ou cenários possíveis.However, it doesn't cover every possible detail or scenario. Em caso de dúvida, consulte as especificações de HTTP.When in doubt, consult the HTTP specifications.

Tipos de mídiaMedia types

Como mencionado anteriormente, os clientes e servidores trocam representações de recursos.As mentioned earlier, clients and servers exchange representations of resources. Por exemplo, em uma solicitação POST, o corpo da solicitação contém uma representação do recurso para criar.For example, in a POST request, the request body contains a representation of the resource to create. Em uma solicitação GET, o corpo da resposta contém uma representação do recurso de busca.In a GET request, the response body contains a representation of the fetched resource.

No protocolo HTTP, formatos são especificados por meio do uso de tipos de mídia, também chamados de tipos MIME.In the HTTP protocol, formats are specified through the use of media types, also called MIME types. Para dados não binários, a maioria das APIs da Web oferecem suporte a JSON (tipo de mídia = application/json) e, possivelmente, a XML (tipo de mídia = application/xml).For non-binary data, most web APIs support JSON (media type = application/json) and possibly XML (media type = application/xml).

O cabeçalho Content-Type em uma solicitação ou resposta especifica o formato da representação.The Content-Type header in a request or response specifies the format of the representation. Aqui está um exemplo de uma solicitação POST que inclui dados JSON:Here is an example of a POST request that includes JSON data:

POST https://adventure-works.com/orders HTTP/1.1
Content-Type: application/json; charset=utf-8
Content-Length: 57

{"Id":1,"Name":"Gizmo","Category":"Widgets","Price":1.99}

Se o servidor não oferece suporte para o tipo de mídia, ele deverá retornar um código de status HTTP 415 (Tipo de mídia sem suporte).If the server doesn't support the media type, it should return HTTP status code 415 (Unsupported Media Type).

Uma solicitação cliente pode incluir um cabeçalho Accept contendo uma lista de tipos de mídia que o cliente aceitará do servidor na mensagem de resposta.A client request can include an Accept header that contains a list of media types the client will accept from the server in the response message. Por exemplo:For example:

GET https://adventure-works.com/orders/2 HTTP/1.1
Accept: application/json

Se o servidor não consegue corresponder a nenhum dos tipos de mídia listados, ele deve retornar um código de status HTTP 406 (Não aceitável).If the server cannot match any of the media type(s) listed, it should return HTTP status code 406 (Not Acceptable).

Métodos GETGET methods

Geralmente, um método GET bem-sucedido retorna o código de status HTTP 200 (OK).A successful GET method typically returns HTTP status code 200 (OK). Se o recurso não puder ser encontrado, o método deve retornar 404 (Não encontrado).If the resource cannot be found, the method should return 404 (Not Found).

Métodos POSTPOST methods

Se um método POST cria um novo recurso, ele retornará o código de status HTTP 201 (Criado).If a POST method creates a new resource, it returns HTTP status code 201 (Created). O URI do novo recurso está incluído no cabeçalho Location da resposta.The URI of the new resource is included in the Location header of the response. O corpo da resposta contém uma representação do recurso.The response body contains a representation of the resource.

Se o método executa algum processamento, mas não cria um novo recurso, pode ser que ele retorne o código de status HTTP 200 e inclua o resultado da operação no corpo da resposta.If the method does some processing but does not create a new resource, the method can return HTTP status code 200 and include the result of the operation in the response body. Como alternativa, se não houver nenhum resultado para retornar, o método pode retornar o código de status HTTP 204 (Sem conteúdo) sem o corpo da resposta.Alternatively, if there is no result to return, the method can return HTTP status code 204 (No Content) with no response body.

Se o cliente coloca os dados inválidos na solicitação, o servidor deve retornar o código de status HTTP 400 (Solicitação incorreta).If the client puts invalid data into the request, the server should return HTTP status code 400 (Bad Request). O corpo da resposta pode conter informações adicionais sobre o erro ou um link para um URI que forneça mais detalhes.The response body can contain additional information about the error or a link to a URI that provides more details.

Métodos PUTPUT methods

Se um método PUT cria um novo recurso, ele retornará o código de status HTTP 201 (Criado), assim como com um método POST.If a PUT method creates a new resource, it returns HTTP status code 201 (Created), as with a POST method. Se o método atualiza um recurso existente, ele retorna 200 (OK) ou 204 (Sem conteúdo).If the method updates an existing resource, it returns either 200 (OK) or 204 (No Content). Em alguns casos, pode não ser possível atualizar um recurso existente.In some cases, it might not be possible to update an existing resource. Nesse caso, considere que pode ser retornado o código de status HTTP 409 (Conflito).In that case, consider returning HTTP status code 409 (Conflict).

Considere a possibilidade de implementar operações HTTP PUT em massa, que podem realizar atualizações em lote para vários recursos em uma coleção.Consider implementing bulk HTTP PUT operations that can batch updates to multiple resources in a collection. A solicitação PUT deve especificar o URI da coleção, enquanto o corpo da solicitação deve especificar os detalhes dos recursos a serem modificados.The PUT request should specify the URI of the collection, and the request body should specify the details of the resources to be modified. Essa abordagem pode ajudar a reduzir a verborragia e a melhorar o desempenho.This approach can help to reduce chattiness and improve performance.

Métodos PATCHPATCH methods

Com uma solicitação PATCH, o cliente envia um conjunto de atualizações para um recurso existente na forma de um documento patch.With a PATCH request, the client sends a set of updates to an existing resource, in the form of a patch document. O servidor processa o documento patch para executar a atualização.The server processes the patch document to perform the update. O documento patch não descreve o recurso inteiro, apenas um conjunto de alterações a serem aplicadas.The patch document doesn't describe the whole resource, only a set of changes to apply. A especificação para o método PATCH (RFC 5789) não define um formato específico para documentos patch.The specification for the PATCH method (RFC 5789) doesn't define a particular format for patch documents. O formato deve ser deduzido a partir do tipo de mídia na solicitação.The format must be inferred from the media type in the request.

Provavelmente JSON seja o formato mais comum de dados para APIs da Web.JSON is probably the most common data format for web APIs. Há dois formatos principais de patch baseado em JSON, os quais são chamados de patch JSON e patch de mesclagem JSON.There are two main JSON-based patch formats, called JSON patch and JSON merge patch.

O patch de mesclagem JSON é um pouco mais simples.JSON merge patch is somewhat simpler. O documento patch tem a mesma estrutura que o recurso JSON original, mas inclui apenas o subconjunto de campos que devem ser alterados ou adicionados.The patch document has the same structure as the original JSON resource, but includes just the subset of fields that should be changed or added. Além disso, um campo pode ser excluído especificando null como o valor do campo no documento patch.In addition, a field can be deleted by specifying null for the field value in the patch document. (Isso significa que o patch de mesclagem não é adequado caso o recurso original possa ter valores nulos explícitos.)(That means merge patch is not suitable if the original resource can have explicit null values.)

Por exemplo, suponha que o recurso original tenha a seguinte representação JSON:For example, suppose the original resource has the following JSON representation:

{
    "name":"gizmo",
    "category":"widgets",
    "color":"blue",
    "price":10
}

Aqui está um patch de mesclagem JSON possível para esse recurso:Here is a possible JSON merge patch for this resource:

{
    "price":12,
    "color":null,
    "size":"small"
}

Isso diz ao priceservidor colorpara atualizar, name excluir category e adicionar, sizeenquanto não for modificado.This tells the server to update price, delete color, and add size, while name and category are not modified. Para obter os detalhes exatos do patch de mesclagem JSON, consulte RFC 7396.For the exact details of JSON merge patch, see RFC 7396. O tipo de mídia para patch de mesclagem JSON é application/merge-patch+json.The media type for JSON merge patch is application/merge-patch+json.

Devido a um significado especial de null no documento patch, o patch de mesclagem não é adequado se o recurso original puder conter valores nulos explícitos.Merge patch is not suitable if the original resource can contain explicit null values, due to the special meaning of null in the patch document. Além disso, o documento patch não especifica o pedido no qual o servidor deve aplicar as atualizações.Also, the patch document doesn't specify the order that the server should apply the updates. Isso pode ou não importar, dependendo dos dados e o domínio.That may or may not matter, depending on the data and the domain. O patch JSON, definido em RFC 6902, é mais flexível.JSON patch, defined in RFC 6902, is more flexible. Ele especifica as alterações como uma sequência de operações a ser aplicada.It specifies the changes as a sequence of operations to apply. As operações incluem adicionar, remover, substituir, copiar e testar (para validar valores).Operations include add, remove, replace, copy, and test (to validate values). O tipo de mídia para patch de JSON é application/json-patch+json.The media type for JSON patch is application/json-patch+json.

Estas são algumas condições comuns de erro que podem ser encontradas ao processar uma solicitação PATCH, juntamente com o código de status HTTP apropriado.Here are some typical error conditions that might be encountered when processing a PATCH request, along with the appropriate HTTP status code.

Condição de erroError condition Código de status HTTPHTTP status code
Não há suporte para o formato de documento patch.The patch document format isn't supported. 415 (Tipo de mídia sem suporte)415 (Unsupported Media Type)
Documento patch malformado.Malformed patch document. 400 (Solicitação incorreta)400 (Bad Request)
O documento patch é válido, mas as alterações não podem ser aplicadas ao recurso em seu estado atual.The patch document is valid, but the changes can't be applied to the resource in its current state. 409 (Conflito)409 (Conflict)

Métodos DELETEDELETE methods

Se a operação de exclusão for bem-sucedida, o servidor Web deve responder com um código de status HTTP 204, indicando que o processo foi tratado com êxito, mas sem nenhuma informação adicional no corpo da resposta.If the delete operation is successful, the web server should respond with HTTP status code 204, indicating that the process has been successfully handled, but that the response body contains no further information. Se o recurso não existir, o servidor Web pode retornar HTTP 404 (Não encontrado).If the resource doesn't exist, the web server can return HTTP 404 (Not Found).

Operações assíncronasAsynchronous operations

Às vezes, uma operação POST, PUT, PATCH ou DELETE pode exigir processamento que leva um tempo para ser concluído.Sometimes a POST, PUT, PATCH, or DELETE operation might require processing that takes a while to complete. Se você aguardar a conclusão antes de enviar uma resposta ao cliente, isso pode causar uma latência inaceitável.If you wait for completion before sending a response to the client, it may cause unacceptable latency. Nesse caso, considere fazer a operação assíncrona.If so, consider making the operation asynchronous. O código de status HTTP 202 (Aceito) retorna para indicar que a solicitação foi aceita para processamento, mas não está concluída.Return HTTP status code 202 (Accepted) to indicate the request was accepted for processing but is not completed.

Você deve expor um ponto de extremidade que retorna o status de uma solicitação assíncrona, de modo que o cliente possa monitorar o status por meio da sondagem do ponto de extremidade de status.You should expose an endpoint that returns the status of an asynchronous request, so the client can monitor the status by polling the status endpoint. Inclua o URI do ponto de extremidade de status no cabeçalho Location da resposta 202.Include the URI of the status endpoint in the Location header of the 202 response. Por exemplo:For example:

HTTP/1.1 202 Accepted
Location: /api/status/12345

Se o cliente enviar uma solicitação GET para esse ponto de extremidade, a resposta deve conter o status atual da solicitação.If the client sends a GET request to this endpoint, the response should contain the current status of the request. Como opção, ela também pode incluir um tempo estimado para conclusão ou um link para cancelar a operação.Optionally, it could also include an estimated time to completion or a link to cancel the operation.

HTTP/1.1 200 OK
Content-Type: application/json

{
    "status":"In progress",
    "link": { "rel":"cancel", "method":"delete", "href":"/api/status/12345" }
}

Se a operação assíncrona criar um novo recurso, o ponto de extremidade de status deve retornar o código de status 303 (Ver outros) após a conclusão da operação.If the asynchronous operation creates a new resource, the status endpoint should return status code 303 (See Other) after the operation completes. A resposta 303 inclui um cabeçalho Location que fornece o URI do novo recurso:In the 303 response, include a Location header that gives the URI of the new resource:

HTTP/1.1 303 See Other
Location: /api/orders/12345

Para obter mais informações, consulte o padrão Asynchronous Request-Reply.For more information, see Asynchronous Request-Reply pattern.

Filtrar e paginar dadosFilter and paginate data

Expor uma coleção de recursos por meio de um único URI pode levar a aplicativos que buscam grandes quantidades de dados quando apenas um subconjunto dessas informações é necessário.Exposing a collection of resources through a single URI can lead to applications fetching large amounts of data when only a subset of the information is required. Por exemplo, suponha que um aplicativo cliente precise localizar todos os pedidos com custo acima de um valor específico.For example, suppose a client application needs to find all orders with a cost over a specific value. Ele pode recuperar todos os pedidos do URI /order e, em seguida, filtrar esses pedidos no lado do cliente.It might retrieve all orders from the /orders URI and then filter these orders on the client side. Fica claro que esse processo é muito ineficiente.Clearly this process is highly inefficient. Ele desperdiça tanto energia de processamento quanto de largura de banda de rede no servidor que hospeda a API da Web.It wastes network bandwidth and processing power on the server hosting the web API.

Em vez disso, a API pode permitir a transmissão de um filtro na cadeia de consulta do URI, como /orders?minCost=n.Instead, the API can allow passing a filter in the query string of the URI, such as /orders?minCost=n. A API da Web é responsável pela análise e pelo tratamento do parâmetro minCost na cadeia de consulta e por retornar os resultados filtrados no lado do servidor.The web API is then responsible for parsing and handling the minCost parameter in the query string and returning the filtered results on the server side.

Solicitações GET sobre os recursos de coleção têm potencial de retornar um grande número de itens.GET requests over collection resources can potentially return a large number of items. Você deve projetar uma API da Web para limitar a quantidade de dados retornados por qualquer solicitação única.You should design a web API to limit the amount of data returned by any single request. Considere a possibilidade de oferecer suporte a cadeias de consulta que especifiquem o número máximo de itens para recuperar e um deslocamento de início para a coleção.Consider supporting query strings that specify the maximum number of items to retrieve and a starting offset into the collection. Por exemplo:For example:

/orders?limit=25&offset=50

Também considere a possibilidade de impor um limite superior na quantidade de itens retornados para ajudar a evitar ataques de negação de serviço.Also consider imposing an upper limit on the number of items returned, to help prevent Denial of Service attacks. Para ajudar aplicativos cliente, solicitações GET que retornam dados paginados também devem incluir algum tipo de metadados que indiquem o número total de recursos disponíveis na coleção.To assist client applications, GET requests that return paginated data should also include some form of metadata that indicate the total number of resources available in the collection.

Você pode usar uma estratégia semelhante para classificar os dados conforme eles são encontrados por meio do fornecimento de um parâmetro de classificação que use um nome de campo como o valor, tal como /orders?sort=ProductID.You can use a similar strategy to sort data as it is fetched, by providing a sort parameter that takes a field name as the value, such as /orders?sort=ProductID. No entanto, essa abordagem pode ter um efeito negativo no cache, pois parâmetros de cadeia de consulta fazem parte do identificador de recurso usado por muitas implementações de cache como a chave para dados armazenados em cache.However, this approach can have a negative effect on caching, because query string parameters form part of the resource identifier used by many cache implementations as the key to cached data.

Você pode estender esse método para limitar os campos retornados para cada item, se cada um deles contiver uma grande quantidade de dados.You can extend this approach to limit the fields returned for each item, if each item contains a large amount of data. Por exemplo, você poderia usar um parâmetro de cadeia de consulta que aceita uma lista de campos delimitada por vírgulas, como /orders?fields=ProductID,Quantity.For example, you could use a query string parameter that accepts a comma-delimited list of fields, such as /orders?fields=ProductID,Quantity.

Forneça padrões significativos a todos os parâmetros opcionais nas cadeias de consulta.Give all optional parameters in query strings meaningful defaults. Por exemplo, defina o parâmetro limit como 10 e o parâmetro offset como 0 se você implementar a paginação, defina o parâmetro sort para a chave do recurso se você implementar ordenação e, por fim, defina o parâmetro fields para todos os campos no recurso se você oferecer suporte a projeções.For example, set the limit parameter to 10 and the offset parameter to 0 if you implement pagination, set the sort parameter to the key of the resource if you implement ordering, and set the fields parameter to all fields in the resource if you support projections.

Suporte a respostas parciais para recursos binários grandesSupport partial responses for large binary resources

Um recurso pode conter campos binários grandes, como arquivos ou imagens.A resource may contain large binary fields, such as files or images. Para superar os problemas causados por conexões não confiáveis e intermitentes e para melhorar os tempos de resposta, considere a possibilidade de habilitar a recuperação desses recursos em partes.To overcome problems caused by unreliable and intermittent connections and to improve response times, consider enabling such resources to be retrieved in chunks. Para isso, a API da Web deve oferecer suporte ao cabeçalho Accept-Ranges para solicitações GET para grandes recursos.To do this, the web API should support the Accept-Ranges header for GET requests for large resources. Esse cabeçalho indica que a operação GET oferece suporte a solicitações parciais.This header indicates that the GET operation supports partial requests. O aplicativo cliente pode enviar solicitações GET que retornam um subconjunto de um recurso, especificado como um intervalo de bytes.The client application can submit GET requests that return a subset of a resource, specified as a range of bytes.

Além disso, considere a possibilidade de implementar solicitações HTTP HEAD para esses recursos.Also, consider implementing HTTP HEAD requests for these resources. Uma solicitação HEAD é semelhante a uma solicitação GET, porém retorna apenas cabeçalhos HTTP que descrevem o recurso com um corpo de mensagem vazio.A HEAD request is similar to a GET request, except that it only returns the HTTP headers that describe the resource, with an empty message body. Um aplicativo cliente pode emitir uma solicitação HEAD para determinar se deve ou não buscar um recurso pelo uso de solicitações GET parciais.A client application can issue a HEAD request to determine whether to fetch a resource by using partial GET requests. Por exemplo:For example:

HEAD https://adventure-works.com/products/10?fields=productImage HTTP/1.1

Eis um exemplo de corpo da resposta:Here is an example response message:

HTTP/1.1 200 OK

Accept-Ranges: bytes
Content-Type: image/jpeg
Content-Length: 4580

O cabeçalho Content-Length dá o tamanho total do recurso, e o cabeçalho Accept-Ranges indica que a operação GET correspondente oferece suporte a resultados parciais.The Content-Length header gives the total size of the resource, and the Accept-Ranges header indicates that the corresponding GET operation supports partial results. O aplicativo cliente pode usar essas informações para recuperar a imagem em partes menores.The client application can use this information to retrieve the image in smaller chunks. A primeira solicitação busca os primeiros 2.500 bytes usando o cabeçalho Range:The first request fetches the first 2500 bytes by using the Range header:

GET https://adventure-works.com/products/10?fields=productImage HTTP/1.1
Range: bytes=0-2499

A mensagem de resposta indica, ao retornar o código de status HTTP 206, que esta é uma resposta parcial.The response message indicates that this is a partial response by returning HTTP status code 206. O cabeçalho Content-Length especifica o número real de bytes retornados no corpo da mensagem (não o tamanho do recurso), enquanto o cabeçalho Content-Range indica que parte do recurso isso é (0-2.499 bytes de 4.580):The Content-Length header specifies the actual number of bytes returned in the message body (not the size of the resource), and the Content-Range header indicates which part of the resource this is (bytes 0-2499 out of 4580):

HTTP/1.1 206 Partial Content

Accept-Ranges: bytes
Content-Type: image/jpeg
Content-Length: 2500
Content-Range: bytes 0-2499/4580

[...]

Uma solicitação subsequente do aplicativo cliente pode recuperar o restante do recurso.A subsequent request from the client application can retrieve the remainder of the resource.

Uma das principais motivações por trás de REST é a que deve ser possível navegar por todo o conjunto de recursos sem exigir conhecimento prévio do esquema de URI.One of the primary motivations behind REST is that it should be possible to navigate the entire set of resources without requiring prior knowledge of the URI scheme. Cada solicitação HTTP GET deve retornar as informações necessárias para localizar os recursos relacionados diretamente ao objeto solicitado por hiperlinks incluídos na resposta, e também deve ser provida de informações descrevendo as operações disponíveis em cada um desses recursos.Each HTTP GET request should return the information necessary to find the resources related directly to the requested object through hyperlinks included in the response, and it should also be provided with information that describes the operations available on each of these resources. Esse conceito é conhecido como HATEOAS, ou Hipertexto como o Mecanismo de Estado do Aplicativo.This principle is known as HATEOAS, or Hypertext as the Engine of Application State. O sistema é efetivamente uma máquina de estado finito, e a resposta para cada solicitação contém as informações necessárias para ir de um estado para outro; nenhuma outra informação deve ser necessária.The system is effectively a finite state machine, and the response to each request contains the information necessary to move from one state to another; no other information should be necessary.

Observação

Atualmente não há padrões nem especificações que definam como modelar o princípio HATEOAS.Currently there are no standards or specifications that define how to model the HATEOAS principle. Os exemplos mostrados nesta seção ilustram uma possível solução.The examples shown in this section illustrate one possible solution.

Por exemplo, para tratar da relação entre um pedido e um cliente, a representação de um pedido pode incluir links que identificam as operações disponíveis para o cliente do pedido.For example, to handle the relationship between an order and a customer, the representation of an order could include links that identify the available operations for the customer of the order. Eis aqui uma representação possível:Here is a possible representation:

{
  "orderID":3,
  "productID":2,
  "quantity":4,
  "orderValue":16.60,
  "links":[
    {
      "rel":"customer",
      "href":"https://adventure-works.com/customers/3",
      "action":"GET",
      "types":["text/xml","application/json"]
    },
    {
      "rel":"customer",
      "href":"https://adventure-works.com/customers/3",
      "action":"PUT",
      "types":["application/x-www-form-urlencoded"]
    },
    {
      "rel":"customer",
      "href":"https://adventure-works.com/customers/3",
      "action":"DELETE",
      "types":[]
    },
    {
      "rel":"self",
      "href":"https://adventure-works.com/orders/3",
      "action":"GET",
      "types":["text/xml","application/json"]
    },
    {
      "rel":"self",
      "href":"https://adventure-works.com/orders/3",
      "action":"PUT",
      "types":["application/x-www-form-urlencoded"]
    },
    {
      "rel":"self",
      "href":"https://adventure-works.com/orders/3",
      "action":"DELETE",
      "types":[]
    }]
}

Nesse exemplo, a matriz links tem um conjunto de links.In this example, the links array has a set of links. Cada link representa uma operação em uma entidade relacionada.Each link represents an operation on a related entity. Os dados para cada link incluem a relação (“cliente”), o URI (https://adventure-works.com/customers/3), o método HTTP e os tipos MIME com suporte.The data for each link includes the relationship ("customer"), the URI (https://adventure-works.com/customers/3), the HTTP method, and the supported MIME types. Essas são todas as informações de que um aplicativo cliente precisa para ser capaz de invocar a operação.This is all the information that a client application needs to be able to invoke the operation.

A matriz links também inclui informações referentes a si sobre o próprio recurso que foram recuperadas.The links array also includes self-referencing information about the resource itself that has been retrieved. Elas apresentam a relação self.These have the relationship self.

O conjunto de links retornados pode mudar, dependendo do estado do recurso.The set of links that are returned may change, depending on the state of the resource. Isso é o que se quer dizer ao se afirmar que o hipertexto é o “mecanismo do estado do aplicativo”.This is what is meant by hypertext being the "engine of application state."

Controlando a versão de uma API da Web RESTfulVersioning a RESTful web API

É muito improvável que uma API da Web permanecerá estática.It is highly unlikely that a web API will remain static. Conforme os requisitos de negócios mudam, novas coleções de recursos podem ser adicionados, as relações entre os recursos podem mudar e a estrutura dos dados nos recursos pode ser alterada.As business requirements change new collections of resources may be added, the relationships between resources might change, and the structure of the data in resources might be amended. Enquanto a atualização de uma API da Web para lidar com requisitos novos ou diferentes é um processo relativamente simples, você deve considerar os efeitos que essas mudanças terão em aplicativos cliente que consomem a API da Web.While updating a web API to handle new or differing requirements is a relatively straightforward process, you must consider the effects that such changes will have on client applications consuming the web API. A questão é que, embora o desenvolvedor projetando e implementando uma API web tenha controle total sobre essa API, o desenvolvedor não tem o mesmo grau de controle sobre aplicativos clientes, que podem ser construídos por organizações de terceiros que operam remotamente.The issue is that although the developer designing and implementing a web API has full control over that API, the developer does not have the same degree of control over client applications, which may be built by third-party organizations operating remotely. A principal prioridade é habilitar aplicativos cliente existentes a continuar funcionando inalterados, permitindo simultaneamente que novos aplicativos cliente tirem proveito das novas funções e recursos.The primary imperative is to enable existing client applications to continue functioning unchanged while allowing new client applications to take advantage of new features and resources.

O controle de versão permite que uma API da Web indique os recursos e as funções que ela expõe, e um aplicativo cliente pode enviar solicitações direcionadas a uma versão específica de uma função ou recurso.Versioning enables a web API to indicate the features and resources that it exposes, and a client application can submit requests that are directed to a specific version of a feature or resource. As seções a seguir descrevem várias abordagens diferentes, cada qual com suas próprias vantagens e desvantagens.The following sections describe several different approaches, each of which has its own benefits and trade-offs.

Sem controle de versãoNo versioning

Essa é a abordagem mais simples e pode ser aceitável para algumas APIs internas.This is the simplest approach, and may be acceptable for some internal APIs. Mudanças significativas poderiam ser representadas como novos recursos ou novos links.Significant changes could be represented as new resources or new links. Adicionar conteúdo aos recursos existentes pode não apresentar uma mudança de ruptura, pois os aplicativos clientes que não esperam ver esse conteúdo irão ignorá-lo.Adding content to existing resources might not present a breaking change as client applications that are not expecting to see this content will ignore it.

Por exemplo, uma solicitação para o URI https://adventure-works.com/customers/3 deve retornar os detalhes de um único cliente contendo os campos id, name e address esperados pelo aplicativo cliente:For example, a request to the URI https://adventure-works.com/customers/3 should return the details of a single customer containing id, name, and address fields expected by the client application:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":3,"name":"Contoso LLC","address":"1 Microsoft Way Redmond WA 98053"}

Observação

Simplificando, as respostas de exemplo mostradas nesta seção não incluem links HATEOAS.For simplicity, the example responses shown in this section do not include HATEOAS links.

Se o campo DateCreated é adicionado ao esquema do recurso de cliente, a resposta terá essa aparência:If the DateCreated field is added to the schema of the customer resource, then the response would look like this:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":3,"name":"Contoso LLC","dateCreated":"2014-09-04T12:11:38.0376089Z","address":"1 Microsoft Way Redmond WA 98053"}

Aplicativos cliente existentes podem continuar funcionando corretamente se forem capazes de ignorar campos não reconhecidos, enquanto os novos aplicativos cliente podem ser projetados para lidar com esse novo campo.Existing client applications might continue functioning correctly if they are capable of ignoring unrecognized fields, while new client applications can be designed to handle this new field. No entanto, se ocorrerem alterações mais radicais ao esquema de recursos (por exemplo, remover ou renomear campos) ou se as relações entre os recursos mudarem, estas poderão constituir alterações significativas que impedem que aplicativos cliente existentes funcionem corretamente.However, if more radical changes to the schema of resources occur (such as removing or renaming fields) or the relationships between resources change then these may constitute breaking changes that prevent existing client applications from functioning correctly. Nessas situações, você deve considerar uma das seguintes abordagens.In these situations, you should consider one of the following approaches.

Controle de versão de URIURI versioning

Cada vez que você modifica a API da Web ou altera o esquema de recursos, você adiciona um número de versão ao URI para cada recurso.Each time you modify the web API or change the schema of resources, you add a version number to the URI for each resource. Os URIs previamente existentes devem continuar a funcionar como antes, recuperando recursos que estão em conformidade com seu esquema original.The previously existing URIs should continue to operate as before, returning resources that conform to their original schema.

Estendendo address o exemplo anterior, se o campo for reestruturado em subcampos streetAddresscontendo city statecada zipCodeparte constituinte do endereço (como , , e ), esta https://adventure-works.com/v2/customers/3versão do recurso pode ser exposta através de um URI contendo um número de versão, tais como:Extending the previous example, if the address field is restructured into subfields containing each constituent part of the address (such as streetAddress, city, state, and zipCode), this version of the resource could be exposed through a URI containing a version number, such as https://adventure-works.com/v2/customers/3:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":3,"name":"Contoso LLC","dateCreated":"2014-09-04T12:11:38.0376089Z","address":{"streetAddress":"1 Microsoft Way","city":"Redmond","state":"WA","zipCode":98053}}

Esse mecanismo de controle de versão é muito simples, mas depende do servidor realizar o roteamento da solicitação para o ponto de extremidade apropriado.This versioning mechanism is very simple but depends on the server routing the request to the appropriate endpoint. No entanto, ele pode se tornar inviável conforme a API da Web amadurece ao passar por várias iterações e o servidor tem que oferecer suporte a um número de versões diferentes.However, it can become unwieldy as the web API matures through several iterations and the server has to support a number of different versions. Além disso, do ponto de vista de um purista, em todos os casos os aplicativos clientes estão buscando os mesmos dados (cliente 3), então o URI não deve ser realmente diferente dependendo da versão.Also, from a purist's point of view, in all cases the client applications are fetching the same data (customer 3), so the URI should not really be different depending on the version. Esse esquema também complica a implementação de HATEOAS, já que todos os links precisarão incluir o número da versão em seus URIs.This scheme also complicates implementation of HATEOAS as all links will need to include the version number in their URIs.

Controle de versão de cadeia de consultaQuery string versioning

Em vez de fornecer vários URIs, você pode especificar a versão do recurso usando um parâmetro dentro da cadeia de consulta acrescentada à solicitação HTTP, como https://adventure-works.com/customers/3?version=2.Rather than providing multiple URIs, you can specify the version of the resource by using a parameter within the query string appended to the HTTP request, such as https://adventure-works.com/customers/3?version=2. O parâmetro de versão, caso seja omitido por aplicativos cliente mais antigos, deve passar a usar um valor padrão significativo, como 1.The version parameter should default to a meaningful value such as 1 if it is omitted by older client applications.

Essa abordagem tem a vantagem de semântica que o mesmo recurso é sempre recuperado do mesmo URI, mas para isso, é necessário que o código que processa a solicitação analise a cadeia de consulta e envie de volta a resposta HTTP apropriada.This approach has the semantic advantage that the same resource is always retrieved from the same URI, but it depends on the code that handles the request to parse the query string and send back the appropriate HTTP response. Essa abordagem também tem as mesmas complicações para implementar HATEOAS como o mecanismo de controle de versão do URI.This approach also suffers from the same complications for implementing HATEOAS as the URI versioning mechanism.

Observação

Alguns navegadores e proxies da Web mais antigos não armazenarão respostas em cache para solicitações que incluam, no URI, uma cadeia de consulta.Some older web browsers and web proxies will not cache responses for requests that include a query string in the URI. Isso pode degradar o desempenho de aplicativos web que usam uma API web e que são executados dentro de um navegador da Web.This can degrade performance for web applications that use a web API and that run from within such a web browser.

Controle de versão de cabeçalhoHeader versioning

Em vez de acrescentar o número de versão como um parâmetro de cadeia de consulta, você pode implementar um cabeçalho personalizado que indica a versão do recurso.Rather than appending the version number as a query string parameter, you could implement a custom header that indicates the version of the resource. Essa abordagem requer que o aplicativo cliente adicione o cabeçalho apropriado a quaisquer solicitações, embora o código que processa a solicitação do cliente possa usar um valor padrão (versão 1) se o cabeçalho da versão for omitido.This approach requires that the client application adds the appropriate header to any requests, although the code handling the client request could use a default value (version 1) if the version header is omitted. Os exemplos a seguir utilizam um cabeçalho personalizado nomeado Cabeçalho Personalizado.The following examples use a custom header named Custom-Header. O valor desse cabeçalho indica a versão da API da Web.The value of this header indicates the version of web API.

Versão 1:Version 1:

GET https://adventure-works.com/customers/3 HTTP/1.1
Custom-Header: api-version=1
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":3,"name":"Contoso LLC","address":"1 Microsoft Way Redmond WA 98053"}

Versão 2:Version 2:

GET https://adventure-works.com/customers/3 HTTP/1.1
Custom-Header: api-version=2
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":3,"name":"Contoso LLC","dateCreated":"2014-09-04T12:11:38.0376089Z","address":{"streetAddress":"1 Microsoft Way","city":"Redmond","state":"WA","zipCode":98053}}

Como nas duas abordagens anteriores, a implementação do HATEOAS requer a inclusão do cabeçalho personalizado apropriado em quaisquer links.As with the previous two approaches, implementing HATEOAS requires including the appropriate custom header in any links.

Controle de versão do tipo de mídiaMedia type versioning

Quando um aplicativo cliente envia uma solicitação HTTP GET para um servidor Web, ele deve estipular o formato do conteúdo que pode manipular usando um cabeçalho Accept, conforme descrito anteriormente nestas diretrizes.When a client application sends an HTTP GET request to a web server it should stipulate the format of the content that it can handle by using an Accept header, as described earlier in this guidance. Frequentemente, a finalidade do cabeçalho Accept é permitir que o aplicativo cliente especifique se o corpo da resposta deve ser XML, JSON ou algum outro formato comum que o cliente possa analisar.Frequently the purpose of the Accept header is to allow the client application to specify whether the body of the response should be XML, JSON, or some other common format that the client can parse. No entanto, é possível definir tipos de mídia personalizados que incluem informações, permitindo que o aplicativo cliente indique qual versão de um recurso esse aplicativo está esperando.However, it is possible to define custom media types that include information enabling the client application to indicate which version of a resource it is expecting. O exemplo a seguir mostra uma solicitação que especifica um cabeçalho Accept com o valor application/vnd.adventure-works.v1+json.The following example shows a request that specifies an Accept header with the value application/vnd.adventure-works.v1+json. O elemento vnd.adventure-works.v1 indica ao servidor Web que ele deve retornar a versão 1 do recurso, enquanto o elemento json especifica que o formato do corpo da resposta deve ser JSON:The vnd.adventure-works.v1 element indicates to the web server that it should return version 1 of the resource, while the json element specifies that the format of the response body should be JSON:

GET https://adventure-works.com/customers/3 HTTP/1.1
Accept: application/vnd.adventure-works.v1+json

O código que processa a solicitação é responsável por processar o cabeçalho Accept e honrá-lo o máximo possível (o aplicativo cliente pode especificar vários formatos no cabeçalho Accept; nesse caso, o servidor Web pode escolher o formato mais apropriado para o corpo de resposta).The code handling the request is responsible for processing the Accept header and honoring it as far as possible (the client application may specify multiple formats in the Accept header, in which case the web server can choose the most appropriate format for the response body). O servidor Web confirma o formato dos dados no corpo da resposta usando o cabeçalho Content-Type:The web server confirms the format of the data in the response body by using the Content-Type header:

HTTP/1.1 200 OK
Content-Type: application/vnd.adventure-works.v1+json; charset=utf-8

{"id":3,"name":"Contoso LLC","address":"1 Microsoft Way Redmond WA 98053"}

Se o cabeçalho Accept não especificar nenhum tipo de mídia conhecido, o servidor Web pode gerar uma mensagem de resposta HTTP 406 (Não Aceitável) ou retornar uma mensagem com um tipo de mídia padrão.If the Accept header does not specify any known media types, the web server could generate an HTTP 406 (Not Acceptable) response message or return a message with a default media type.

Essa abordagem é possivelmente o mais puro dos mecanismos de controle de versão e aplica-se naturalmente a HATEOAS, que pode incluir o tipo MIME dos dados relacionados em links de recursos.This approach is arguably the purest of the versioning mechanisms and lends itself naturally to HATEOAS, which can include the MIME type of related data in resource links.

Observação

Quando você seleciona uma estratégia de controle de versão, você também deve considerar as implicações de desempenho, especialmente no armazenamento em cache no servidor Web.When you select a versioning strategy, you should also consider the implications on performance, especially caching on the web server. O controle de versão do URI e esquemas de controle de versão de cadeia de consulta facilitam o armazenamento em cache na medida em que, a cada vez, a mesma combinação de URI/cadeia de consulta refere-se aos mesmos dados.The URI versioning and Query String versioning schemes are cache-friendly inasmuch as the same URI/query string combination refers to the same data each time.

Os mecanismos de controle de versão do cabeçalho e do tipo de mídia, normalmente, exigem lógica adicional para examinar os valores no cabeçalho personalizado ou no cabeçalho Accept.The Header versioning and Media Type versioning mechanisms typically require additional logic to examine the values in the custom header or the Accept header. Em um ambiente de grande escala, muitos clientes usando versões diferentes de uma API da Web podem resultar em uma quantidade significativa de dados duplicados em um cache do lado do servidor.In a large-scale environment, many clients using different versions of a web API can result in a significant amount of duplicated data in a server-side cache. Esse problema pode se tornar importante se um aplicativo cliente se comunica com um servidor Web através de um proxy que implementa caching, e que encaminha uma solicitação ao servidor Web somente se ele não mantém atualmente uma cópia dos dados solicitados em seu cache.This issue can become acute if a client application communicates with a web server through a proxy that implements caching, and that only forwards a request to the web server if it does not currently hold a copy of the requested data in its cache.

Abrir Iniciativa de APIOpen API Initiative

A Open API Initiative foi criada por um consórcio do setor para padronizar descrições de API REST entre fornecedores.The Open API Initiative was created by an industry consortium to standardize REST API descriptions across vendors. Como parte dessa iniciativa, a especificação de Swagger 2.0 foi renomeada como OAS (OpenAPI Specification) e colocada sob a iniciativa de API aberta.As part of this initiative, the Swagger 2.0 specification was renamed the OpenAPI Specification (OAS) and brought under the Open API Initiative.

Talvez você queira adotar a OpenAPI para suas APIs Web.You may want to adopt OpenAPI for your web APIs. Considere o seguinte:Some points to consider:

  • A OpenAPI Specification vem com um conjunto de diretrizes insistentes sobre como uma API REST deve ser criada.The OpenAPI Specification comes with a set of opinionated guidelines on how a REST API should be designed. Isso apresenta vantagens para a interoperabilidade, mas requer mais cuidado durante o design de sua API para ficar de acordo com a especificação.That has advantages for interoperability, but requires more care when designing your API to conform to the specification.

  • A OpenAPI promove uma abordagem de primeiro contrato, em vez de uma primeira abordagem de implementação.OpenAPI promotes a contract-first approach, rather than an implementation-first approach. Primeiro contato significa que você projeta o contrato da API (a interface) primeiro e então escreve o código que implementa o contrato.Contract-first means you design the API contract (the interface) first and then write code that implements the contract.

  • Ferramentas como o Swagger podem gerar bibliotecas de cliente ou a documentação de contratos de API.Tools like Swagger can generate client libraries or documentation from API contracts. Por exemplo, consulte ASP.NET páginas de ajuda da API da Web usando o Swagger.For example, see ASP.NET Web API help pages using Swagger.

Mais informaçõesMore information