Design de API WebWeb API design

A maioria das aplicações Web modernas expõem APIs que os clientes podem utilizar para interagir com a aplicação.Most modern web applications expose APIs that clients can use to interact with the application. Uma API Web bem estruturada deve suportar:A well-designed web API should aim to support:

  • Independência da plataforma.Platform independence. Qualquer cliente deve conseguir chamar a API, independentemente de como a API é implementada internamente.Any client should be able to call the API, regardless of how the API is implemented internally. Tal requer a utilização de protocolos padrão, assim como um mecanismo a partir do qual o cliente e o serviço Web podem acordar qual o formato dos dados a trocar.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 Web deve ter a capacidade de evoluir e adicionar funcionalidades de forma independente a partir das aplicações cliente.The web API should be able to evolve and add functionality independently from client applications. À medida que a API evolui, as aplicações cliente existentes devem continuar a funcionar sem modificação.As the API evolves, existing client applications should continue to function without modification. Toda a funcionalidade deve ser detectável para que os aplicativos cliente possam usá-lo por completo.All functionality should be discoverable so that client applications can fully use it.

Estas orientações descrevem os problemas que deve ter em consideração quando conceber uma API Web.This guidance describes issues that you should consider when designing a web API.

Introdução à RESTIntroduction to REST

Em 2000, Roy Fielding propôs a REST (Representational State Transfer) como uma abordagem arquitetónica à conceção de serviços Web.In 2000, Roy Fielding proposed Representational State Transfer (REST) as an architectural approach to designing web services. A REST é um estilo de arquitetura para a criação de sistemas distribuídos com base na 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 associada ao HTTP.REST is independent of any underlying protocol and is not necessarily tied to HTTP. No entanto, as implementações da REST mais comuns utilizam HTTP como o protocolo da aplicação e este guia centra-se na conceçã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 associa a implementação da API ou dos 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 pode ser escrito na ASP.NET e as aplicações cliente podem utilizar qualquer linguagem ou conjunto de ferramentas, os quais podem gerar pedidos de HTTP e analisar as 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.

Seguem-se alguns dos princípios de design principais das APIs RESTful com HTTP:Here are some of the main design principles of RESTful APIs using HTTP:

  • As APIs REST são concebidas em torno dos recursos, que são qualquer tipo de objeto, dados ou serviço que pode ser acedido 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, 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 de uma encomenda de cliente específico 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 ao trocar representações de recursos.Clients interact with a service by exchanging representations of resources. Muitas APIs Web utilizam o JSON como o formato de troca.Many web APIs use JSON as the exchange format. Por exemplo, um pedido GET para o URI listado acima pode devolver 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 utilizam uma interface uniforme, que ajuda a desacoplar as implementações do cliente e do serviço.REST APIs use a uniform interface, which helps to decouple the client and service implementations. Para APIs REST criadas 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 utilizam um modelo de pedido sem estado.REST APIs use a stateless request model. Os pedidos HTTP devem ser independentes e podem ocorrer em qualquer ordem, pelo que não é exequível manter informações no estado transitório entre os pedidos.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 pedido 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. Esta restrição permite que os serviços Web sejam altamente dimensionáveis, uma vez que não é necessário manter qualquer 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. Qualquer servidor pode processar um pedido de qualquer cliente.Any server can handle any request from any client. Dito isto, outros fatores podem limitar a escalabilidade.That said, other factors can limit scalability. Por exemplo, muitos serviços Web gravam em um armazenamento de dados de back-end, o que pode ser difícil de escalar horizontalmente. Para obter mais informações sobre estratégias para expandir um armazenamento de dados, consulte horizontal, vertical e particionamento de dados 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 estão condicionadas por ligações de hipermédia contidas na representação.REST APIs are driven by hypermedia links that are contained in the representation. Por exemplo, o seguinte mostra uma representação JSON de uma encomenda.For example, the following shows a JSON representation of an order. Contém ligações para obter ou atualizar o cliente associado à encomenda.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 o seguinte modelo de maturidade para as APIs Web:In 2008, Leonard Richardson proposed the following maturity model for web APIs:

  • Nível 0: definir um URI e todas as operações são pedidos POST enviados a este URI.Level 0: Define one URI, and all operations are POST requests to this URI.
  • Nível 1: criar URIs separados para recursos individuais.Level 1: Create separate URIs for individual resources.
  • Nível 2: utilizar métodos HTTP para definir operações nos recursos.Level 2: Use HTTP methods to define operations on resources.
  • Nível 3: utiliza hipermédiar(HATEOAS, descrito abaixo).Level 3: Use hypermedia (HATEOAS, described below).

O nível 3 corresponde a uma verdadeira API RESTful, 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 Web publicadas ficam em um lugar próximo do nível 2.In practice, many published web APIs fall somewhere around level 2.

Organizar a API em torno dos recursosOrganize the API around resources

Concentre-se nas entidades de negócios expostas pela API Web.Focus on the business entities that the web API exposes. Por exemplo, num sistema de comércio eletrónico, as entidades primárias podem ser os clientes e as encomendas.For example, in an e-commerce system, the primary entities might be customers and orders. Pode criar uma encomenda através do envio de um pedido HTTP POST que contém as informações da encomenda.Creating an order can be achieved by sending an HTTP POST request that contains the order information. A resposta HTTP indica se a encomenda foi realizada com sucesso ou não.The HTTP response indicates whether the order was placed successfully or not. Sempre que possível, os URIs de recursos devem ser baseados em substantivos (o recurso) e não 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ísico.A resource doesn't have to be based on a single physical data item. Por exemplo, um recurso de encomenda pode ser implementado internamente como várias tabelas numa base 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 espelham a estrutura interna de uma base de dados.Avoid creating APIs that simply mirror the internal structure of a database. O objetivo da REST consiste em modelar entidades e as operações que uma aplicação pode realizar 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.

As entidades são, muitas vezes, agrupadas em coleções (encomendas, clientes).Entities are often grouped together into collections (orders, customers). Uma coleção é um recurso individual do item numa coleção e deve ter o 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 URI seguinte pode representar a coleção de encomendas:For example, the following URI might represent the collection of orders:

https://adventure-works.com/orders

O envio de um pedido HTTP GET para o URI da coleção produz 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 tem também o seu próprio URI exclusivo.Each item in the collection also has its own unique URI. Um pedido HTTP GET enviado ao URI do item devolve 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, ajuda utilizar nomes no plural para os URIs que referenciam 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 numa 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 o 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. Esta abordagem ajuda a manter a API Web intuitiva.This approach helps to keep the web API intuitive. Além disso, muitas estruturas API Web podem encaminhar pedidos com base nos caminhos URI parametrizados, pelo que pode 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}.

Considere também as relações entre os diferentes tipos de recursos e a forma como pode expor estas 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 todas as encomendas do cliente 5.For example, the /customers/5/orders might represent all of the orders for customer 5. Pode também seguir na outra direção e representar a associação de uma encomenda de volta para 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, se expandir demasiado este modelo, poderá tornar-se complicado implementá-lo.However, extending this model too far can become cumbersome to implement. Uma melhor solução consiste em fornecer ligações navegáveis para recursos associados no corpo da mensagem da resposta HTTP.A better solution is to provide navigable links to associated resources in the body of the HTTP response message. Esse mecanismo é descrito mais detalhadamente na seção usar HATEOAS para habilitar a navegação para 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 permitem a um cliente navegar através de vários níveis de relações, tal 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, este nível de complexidade pode ser difícil de manter e não oferecerá nenhum flexibilidade se as relações entre os recursos forem alteradas 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. Assim que uma aplicação possui uma referência para um recurso, deve ser possível utilizar esta 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 pelo URI /customers/1/orders para localizar todas as encomendas do cliente 1 e, em seguida, por /orders/99/products para localizar os produtos nesta encomenda.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 a necessidade de URIs de recursos mais complexos do que collection/item/collection.Avoid requiring resource URIs more complex than collection/item/collection.

Outro fator é que todos os pedidos Web impõem uma carga no servidor Web.Another factor is that all web requests impose a load on the web server. Quantos mais pedidos, maior a carga.The more requests, the bigger the load. Por conseguinte, tente evitar APIs Web “conversadoras” 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. Este tipo de API pode exigir que uma aplicação cliente envie vários pedidos para localizar todos os dados necessários.Such an API may require a client application to send multiple requests to find all of the data that it requires. Em vez disso, pode querer desnormalizar os dados e combinar informações relacionadas com recursos maiores que podem ser obtidos com um único pedido.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, tem de equilibrar esta abordagem com o custo da obtenção de dados que não são necessários para o cliente.However, you need to balance this approach against the overhead of fetching data that the client doesn't need. A obtenção de objetos de grande dimensão pode aumentar a latência de um pedido e implicar custos de largura de banda adicionais.Retrieving large objects can increase the latency of a request and incur additional bandwidth costs. Para obter mais informações sobre estes antipadrões de desempenho, veja Antipadrão E/S Chatty e Antipadrão de Obtenção Externa.For more information about these performance antipatterns, see Chatty I/O and Extraneous Fetching.

Evite introduzir dependências entre a API Web e as origens de dados subjacentes.Avoid introducing dependencies between the web API and the underlying data sources. Por exemplo, se os dados estiverem armazenados na base de dados relacional, a API Web não terá de 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, trata-se provavelmente de uma má conceção.In fact, that's probably a poor design. Em vez disso, considere a API Web como uma abstração da base de dados.Instead, think of the web API as an abstraction of the database. Se necessário, introduza uma camada de mapa entre a base de dados e a API Web.If necessary, introduce a mapping layer between the database and the web API. Dessa forma, as aplicações cliente são isoladas das alterações no esquema da base 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 cada operação implementada por uma API Web num recurso específico.Finally, it might not be possible to map every operation implemented by a web API to a specific resource. Pode processar estes cenários sem recursos através de pedidos HTTP que invocam uma função e devolvem 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 Web que implementa operações de cálculo simples, tal como adicionar e subtrair, pode fornecer URIs que expõem estas operações como pseudorrecursos e utiliza 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 que contém 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, utilize estes formulários de URIs 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 diversos métodos que atribuem significado semântico a um pedido.The HTTP protocol defines a number of methods that assign semantic meaning to a request. Os métodos HTTP comuns utilizados pelas APIs Web RESTful são:The common HTTP methods used by most RESTful web APIs are:

  • GET: obtém 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 pedido.The body of the response message contains the details of the requested resource.
  • POST: cria um novo recurso no URI especificado.POST creates a new resource at the specified URI. O corpo da mensagem de pedido contém os detalhes do novo recurso.The body of the request message provides the details of the new resource. Tenha em atenção que POST também pode ser utilizado para acionar as operações que não criam realmente recursos.Note that POST can also be used to trigger operations that don't actually create resources.
  • PUT: cria ou substitui o recurso no URI especificado.PUT either creates or replaces the resource at the specified URI. O corpo da mensagem de pedido especifica o recurso a ser criado ou atualizado.The body of the request message specifies the resource to be created or updated.
  • PATCH: realiza uma atualização parcial de um recurso.PATCH performs a partial update of a resource. O corpo do pedido especifica o conjunto de alterações a aplicar ao recurso.The request body specifies the set of changes to apply to the resource.
  • DELETE: remove o recurso no URI especificado.DELETE removes the resource at the specified URI.

O efeito de um pedido específico deve depender do facto de um 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 comércio eletrônico.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 GETGET PUTPUT DELETEDELETE
/customers/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
/customers/1/customers/1 ErroError Obter os detalhes do cliente 1Retrieve the details for customer 1 Atualizar os detalhes do cliente 1, se existirUpdate the details of customer 1 if it exists Remover o cliente 1Remove customer 1
/customers/1/orders/customers/1/orders Criar uma nova encomenda para o cliente 1Create a new order for customer 1 Obter todas as encomendas do cliente 1Retrieve all orders for customer 1 Atualização em massa das encomendas do cliente 1Bulk update of orders for customer 1 Remover todas as encomendas 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.

  • Um pedido POST cria um recurso.A POST request creates a resource. O servidor atribui um URI ao novo recurso e devolve-o ao cliente.The server assigns a URI for the new resource, and returns that URI to the client. No modelo REST, aplica frequentemente pedidos POST às 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. Um pedido POST também pode ser utilizado para enviar dados para processamento de um recurso existente, sem a criação de qualquer novo recurso.A POST request can also be used to submit data for processing to an existing resource, without any new resource being created.

  • Um pedido PUT cria um recurso ou atualiza um 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 do pedido contém uma representação completa do recurso.The request body contains a complete representation of the resource. Se já existir um recurso com este URI, será substituído.If a resource with this URI already exists, it is replaced. Caso contrário, um novo recurso será criado se o servidor suportar fazê-lo.Otherwise a new resource is created, if the server supports doing so. Os pedidos PUT são mais frequentemente aplicados aos recursos compostos por itens individuais, tal 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 suportar atualizações, mas não a criação através do método PUT.A server might support updates but not creation via PUT. O suporte da criação através do método PUT depende se o cliente pode atribuir de forma significativa um URI a um recurso antes de este existir.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 for possível, utilize POST para criar recursos e PUT ou PATCH para atualizar.If not, then use POST to create resources and PUT or PATCH to update.

  • Um pedido PATCH realiza uma atualização parcial de 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 do pedido especifica um conjunto de alterações a aplicar ao recurso.The request body specifies a set of changes to apply to the resource. Este procedimento pode ser mais eficiente do que utilizar PUT, uma vez que o cliente envia apenas as alterações, não a representação do recurso completa.This can be more efficient than using PUT, because the client only sends the changes, not the entire representation of the resource. Tecnicamente, PATCH também poderá criar um novo recurso (ao especificar um conjunto de atualizações para um recurso “nulo”) se o servidor o suportar.Technically PATCH can also create a new resource (by specifying a set of updates to a "null" resource), if the server supports this.

Os pedidos PUT têm de ser idempotentes.PUT requests must be idempotent. Se um cliente enviar o mesmo pedido PUT várias vezes, os resultados deverão ser sempre iguais (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 é garantido que os pedidos POST e PATCH sejam idempotentes.POST and PATCH requests are not guaranteed to be idempotent.

Conformidade com a semântica HTTPConform to HTTP semantics

Esta secção descreve algumas considerações comuns para criar uma API em conformidade com a especificação HTTP.This section describes some typical considerations for designing an API that conforms to the HTTP specification. No entanto, não abrange todos os recursos ou cenário possíveis.However, it doesn't cover every possible detail or scenario. Quando em dúvida, consulte as especificações HTTP.When in doubt, consult the HTTP specifications.

Tipos de suporteMedia types

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

No protocolo HTTP, os formatos são especificados através da utilização de tipos de suporte, também designados por tipos de 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 maior parte das APIs Web suporta JSON (tipo de suporte = applicat/json) e, possivelmente, XML (tipo de suporte = 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 num pedido ou numa resposta especifica o formato da representação.The Content-Type header in a request or response specifies the format of the representation. Veja a seguir um exemplo de um pedido 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 suportar o tipo de suporte, deverá devolver o código de estado HTTP 415 (Tipo de Suporte não Suportado).If the server doesn't support the media type, it should return HTTP status code 415 (Unsupported Media Type).

Um pedido de cliente pode incluir um cabeçalho Accept que contém uma lista de tipos de suporte, que o cliente aceita 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 conseguir encontrar nenhum dos tipos de suporte listados, deverá devolver o código de estado 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

Por norma, um método GET bem-sucedido devolve o código de estado HTTP 200 (OK).A successful GET method typically returns HTTP status code 200 (OK). Se não conseguir localizar o recurso, o método deverá devolver 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 criar um novo recurso, devolverá o código de estado 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 realizar algum processamento, mas não criar um novo recurso, o método poderá devolver um código de estado HTTP 200 e incluir 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. Em alternativa, se não for devolvido nenhum resultado, o método poderá devolver o código de estado HTTP 204 (Sem Conteúdo) sem nenhum corpo de 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 colocar dados inválidos no pedido, o servidor deverá devolver o código de estado HTTP 400 (Pedido Incorreto).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 uma ligação para um URI que fornece 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 criar um novo recurso, devolverá o código de estado HTTP 201 (Criado), tal como 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 atualizar um recurso existente, devolverá 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 devolver o código de estado HTTP 409 (Conflito).In that case, consider returning HTTP status code 409 (Conflict).

Pondere implementar operações HTTP PUT em massa, que podem realizar atualizações em lote para vários recursos numa coleção.Consider implementing bulk HTTP PUT operations that can batch updates to multiple resources in a collection. O pedido PUT deve especificar o URI da coleção e o corpo do pedido 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. Esta abordagem pode ajudar a reduzir o diálogo e a melhorar o desempenho.This approach can help to reduce chattiness and improve performance.

Métodos PATCHPATCH methods

Com um pedido PATCH, o cliente envia um conjunto de atualizações para um recurso existente, sob a forma de um documento de 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 de patch para realizar a atualização.The server processes the patch document to perform the update. O documento de patch não descreve todo o recurso, mas apenas um conjunto de alterações a aplicar.The patch document doesn't describe the whole resource, only a set of changes to apply. A especificação do método PATCH (RFC 5789) não define um formato específico para os documentos de patch.The specification for the PATCH method (RFC 5789) doesn't define a particular format for patch documents. O formato deve ser inferido a partir do tipo de suporte no pedido.The format must be inferred from the media type in the request.

JSON é provavelmente o formato de dados mais comum para as APIs Web.JSON is probably the most common data format for web APIs. Existem dois formatos principais de patch baseados em JSON, denominados patch JSON e patch de intercalação JSON.There are two main JSON-based patch formats, called JSON patch and JSON merge patch.

O patch de intercalação JSON é um pouco mais simples.JSON merge patch is somewhat simpler. O documento de patch tem a mesma estrutura que o recurso JSON original, mas inclui apenas o subconjunto dos 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 eliminado ao especificar null para o valor do campo no documento de patch.In addition, a field can be deleted by specifying null for the field value in the patch document. (Tal significa que o patch de intercalação não será adequado se o recurso original tiver 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 tem a seguinte representação JSON:For example, suppose the original resource has the following JSON representation:

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

Segue-se um possível patch de intercalação JSON para este recurso:Here is a possible JSON merge patch for this resource:

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

Isso diz ao servidor para atualizar price, excluir colore adicionar size, enquanto name e category não são modificados.This tells the server to update price, delete color, and add size, while name and category are not modified. Para obter detalhes exatos sobre o patch de intercalação JSON, veja RFC 7396.For the exact details of JSON merge patch, see RFC 7396. O tipo de mídia para o patch de mesclagem JSON é application/merge-patch+json.The media type for JSON merge patch is application/merge-patch+json.

O patch de intercalação não será adequado se o recurso original contiver valores nulos explícitos, devido a um significado especial de null no documento de patch.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 de patch não especifica a ordem pela qual o servidor deve aplicar as atualizações.Also, the patch document doesn't specify the order that the server should apply the updates. Tal pode ou não ser relevante, uma vez que depende dos dados e do 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. Especifica as alterações como uma sequência de operações a aplicar.It specifies the changes as a sequence of operations to apply. As operações incluem adicionar, remover, substituir, copiar e testar (para validar os valores).Operations include add, remove, replace, copy, and test (to validate values). O tipo de mídia para o patch JSON é application/json-patch+json.The media type for JSON patch is application/json-patch+json.

Seguem-se algumas condições de erro comuns que podem ser encontradas ao processar um pedido PATCH, juntamente com o código de estado HTTP adequado.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 estado de HTTPHTTP status code
O formato do documento de patch não é suportado.The patch document format isn't supported. 415 (Tipo de Suporte não Suportado)415 (Unsupported Media Type)
Documento de patch com formato incorreto.Malformed patch document. 400 (Pedido Incorreto)400 (Bad Request)
O documento de patch é válido, mas as alterações não podem ser aplicadas ao recurso no 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 eliminação for-bem sucedida, o servidor Web deverá responder com o código de estado HTTP 204, que indica que o processo foi processado com sucesso, mas que o corpo da resposta não contém informações adicionais.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 poderá devolver 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 demora um pouco para ser concluída.Sometimes a POST, PUT, PATCH, or DELETE operation might require processing that takes a while to complete. Se aguardar pela conclusão antes de enviar uma resposta ao cliente, poderá causar uma latência inaceitável.If you wait for completion before sending a response to the client, it may cause unacceptable latency. Se assim for, considere realizar a operação de forma assíncrona.If so, consider making the operation asynchronous. Devolva o código de estado HTTP 202 (Aceite) para indicar que o pedido foi aceite para processamento, mas não foi concluído.Return HTTP status code 202 (Accepted) to indicate the request was accepted for processing but is not completed.

Deve expor um ponto final que devolve o estado de um pedido assíncrono, pelo que o cliente pode monitorizar o estado ao consultar o ponto final do estado.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. Inclui o URI do ponto final do estado 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 um pedido GET para este ponto final, a resposta deverá conter o estado atual do pedido.If the client sends a GET request to this endpoint, the response should contain the current status of the request. Opcionalmente, também pode incluir um tempo estimado para a conclusão ou uma ligação 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 final de estado deverá devolver o código de estado 303 (Ver Outro) 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. Na resposta 303, inclua um cabeçalho Location para fornecer 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 padrão assíncrono de solicitação-resposta.For more information, see Asynchronous Request-Reply pattern.

Filtrar e paginar dadosFilter and paginate data

A exposição de uma coleção de recursos através de um único URI pode levar as aplicações à obtenção de grandes quantidades de dados quando é preciso apenas um subconjunto das informações.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 uma aplicação cliente precisa de localizar todas as encomendas com um custo com um valor específico.For example, suppose a client application needs to find all orders with a cost over a specific value. Este pode obter todas as encomendas a partir do URI /orders e, em seguida, filtrá-las do lado do cliente.It might retrieve all orders from the /orders URI and then filter these orders on the client side. Claramente, este processo é altamente ineficaz.Clearly this process is highly inefficient. Desperdiça largura de banda da rede e capacidade de processamento no servidor que aloja a API 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, tal 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 é, então, responsável por analisar e manipular o parâmetro minCost na cadeia de caracteres de consulta e 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.

Os pedidos GET sobre recursos de coleção podem, potencialmente, devolver um grande número de itens.GET requests over collection resources can potentially return a large number of items. Deve criar uma API Web para limitar a quantidade de dados devolvidos por qualquer pedido Web único.You should design a web API to limit the amount of data returned by any single request. Considere suportar cadeias de consulta que especificam o número máximo de itens a obter e um deslocamento inicial 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

Considere também impor um limite superior do número de itens devolvidos, para ajudar a impedir ataques Denial of Service.Also consider imposing an upper limit on the number of items returned, to help prevent Denial of Service attacks. Para ajudar as aplicações cliente, os pedidos GET que devolvem dados paginados também devem incluir alguma forma de metadados que indique 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.

Pode utilizar uma estratégia semelhante para ordenar os dados à medida que são obtidos ao fornecer um parâmetro de ordenação que aceita 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, esta abordagem pode ter um efeito negativo na colocação em cache, uma vez que os parâmetros fazem parte da cadeia de consulta do identificador de recursos utilizada por várias implementações de cache, tal como a chave para os dados 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.

Pode expandir esta abordagem para limitar os campos devolvidos em cada item, se cada item 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, pode utilizar um parâmetro de cadeia de consulta que aceita uma lista de campos separados por vírgulas, tal 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.

Escolha predefinições significativas para 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 implementar a paginação, defina o parâmetro de ordenação como a chave do recurso se implementar a ordenação e defina o parâmetro fields como todos os campos no recurso, se suportar 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.

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

Um recurso pode conter campos binários grandes, tal como ficheiros ou imagens.A resource may contain large binary fields, such as files or images. Para ultrapassar os problemas causados por ligações pouco fiáveis e intermitentes, e para melhorar os tempos de resposta, considere ativar estes recursos para serem obtidos em segmentos.To overcome problems caused by unreliable and intermittent connections and to improve response times, consider enabling such resources to be retrieved in chunks. Para tal, a API Web deve suportar o cabeçalho Accept-Ranges de pedidos GET para recursos grandes.To do this, the web API should support the Accept-Ranges header for GET requests for large resources. Este cabeçalho indica que a operação GET suporta pedidos parciais.This header indicates that the GET operation supports partial requests. A aplicação cliente pode submeter pedidos GET que devolvem 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 implementar pedidos de HTTP HEAD para estes recursos.Also, consider implementing HTTP HEAD requests for these resources. Um pedido HEAD é semelhante a um pedido GET, só que devolve apenas os 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. Uma aplicação cliente pode emitir um pedido HEAD para determinar se deve obter um recurso com pedidos 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

Segue-se uma mensagem de resposta de exemplo: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 fornece o tamanho total do recurso e o cabeçalho Accept-Ranges indica que a operação GET correspondente suporta 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. A aplicação cliente pode utilizar estas informações para obter a imagem em segmentos mais pequenos.The client application can use this information to retrieve the image in smaller chunks. O primeiro pedido obtém os primeiros 2500 bytes com 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 que esta é uma resposta parcial ao devolver o código de estado HTTP 206.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 devolvidos no corpo da mensagem (não o tamanho do recurso) e o cabeçalho Content-Range indica de qual a parte do recurso se trata (bytes 0-2499 de 4580):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

[...]

Um pedido subsequente da aplicação cliente pode obter o resto do recurso.A subsequent request from the client application can retrieve the remainder of the resource.

Uma das motivações principais atrás da REST é a possibilidade de navegar por todo o conjunto de recursos sem a necessidade de conhecer anteriormente o esquema do 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 pedido HTTP GET deve devolver as informações necessárias para encontrar os recursos relacionados diretamente com o objeto pedido através de hiperligações incluídas na resposta e também deve ser fornecido com as informações que descrevem as operações disponíveis em cada um destes 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. Este princípio é conhecido como HATEOAS ou Hypertext como o Motor do Estado da Aplicação.This principle is known as HATEOAS, or Hypertext as the Engine of Application State. Com efeito, o sistema é uma máquina de estado finito e a resposta a cada pedido contém as informações necessárias para mover de um estado para outro. Não devem ser necessárias outras informações.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.

Nota

Atualmente, não existem normas nem especificações que definem como modelar o princípio HATEOAS.Currently there are no standards or specifications that define how to model the HATEOAS principle. Os exemplos apresentados nesta secção mostram uma solução possível.The examples shown in this section illustrate one possible solution.

Por exemplo, para lidar com a relação entre uma encomenda e um cliente, a representação de uma encomenda pode incluir ligações que identificam as operações disponíveis para o cliente de uma encomenda.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. Segue-se 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":[]
    }]
}

Neste exemplo, a matriz links tem um conjunto de ligações.In this example, the links array has a set of links. Cada ligação representa uma operação numa entidade relacionada.Each link represents an operation on a related entity. Os dados de cada ligação incluem a relação (“customer”), o URI (https://adventure-works.com/customers/3), o método HTTP e os tipos de MIME suportados.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. Estas são todas as informações que uma aplicação cliente precisa para conseguir 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 de autorreferência sobre o próprio recurso que foi obtido.The links array also includes self-referencing information about the resource itself that has been retrieved. Este tem a relação self.These have the relationship self.

Pode alterar o conjunto de ligações devolvido, dependendo do estado do recurso.The set of links that are returned may change, depending on the state of the resource. Isto é o que significa quando se diz que o hipertexto é o “motor do estado da aplicação”.This is what is meant by hypertext being the "engine of application state."

Controlo de versões de uma API RESTful WebVersioning a RESTful web API

É muito pouco provável que uma API Web permaneça estática.It is highly unlikely that a web API will remain static. À medida que os requisitos comerciais se alteram, novas coleções de recursos poderão ser adicionadas, as relações entre os recursos poderão mudar e a estrutura dos dados nos recursos poderá ser corrigida.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 Web para processar requisitos novos ou diferentes é um processo relativamente simples, tem de considerar os efeitos que essas alterações vão ter em aplicações cliente a consumir API 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. O problema é que, embora o desenvolvedor que projeta e implementa uma API da Web tenha controle total sobre essa API, o desenvolvedor não tem o mesmo grau de controle sobre os aplicativos cliente, que podem ser criados por organizações de terceiros operando 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. O fundamento principal consiste em permitir que aplicações cliente existentes continuem a funcionar inalteradas, ao mesmo tempo que permitem que novas aplicações cliente tirem partido das novas funcionalidades 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 controlo de versões permite a uma API Web indicar as funcionalidades e os recursos que a mesma expõe e uma aplicação cliente pode submeter pedidos que são direcionados para uma versão específica de um recurso ou uma funcionalidade.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 secções seguintes descrevem várias abordagens diferentes, cada uma com os seus próprios benefícios e compromissos.The following sections describe several different approaches, each of which has its own benefits and trade-offs.

Sem controlo de versõesNo versioning

Esta é 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. Alterações significativas podem ser representadas como novos recursos ou novos links.Significant changes could be represented as new resources or new links. Adicionar conteúdo a recursos existentes pode não apresentar uma alteração significativa, já que aplicativos cliente que não estão esperando 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 id, namee address campos 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"}

Nota

Para simplicidade, as respostas do exemplo apresentadas nesta secção não incluem ligações HATEOAS.For simplicity, the example responses shown in this section do not include HATEOAS links.

Se o campo DateCreated for adicionado ao esquema dos recursos do cliente, a resposta deverá ter o seguinte aspeto: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"}

As aplicações cliente existentes podem continuar a funcionar corretamente se tiverem a capacidade de ignorar campos não reconhecidos, enquanto as novas aplicações cliente podem ser concebidas para processar este 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 mais alterações radicais ao esquema de recursos (por exemplo, remover ou renomear os campos) ou as relações entre os recursos forem alteradas, estas poderão constituir alterações recentes que impedem que as aplicações 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 abordagens a seguir.In these situations, you should consider one of the following approaches.

Controlo de versões de URIURI versioning

Sempre que modifica a API Web ou altera o esquema de recursos, adiciona um número de versão ao URI de 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 anteriormente existentes devem continuar a funcionar como antes, devolvendo recursos que estão em conformidade com o esquema original.The previously existing URIs should continue to operate as before, returning resources that conform to their original schema.

Estendendo o exemplo anterior, se o campo address for reestruturado em subcampos contendo cada parte constituinte do endereço (como streetAddress, city, statee zipCode), essa versão do recurso poderá ser exposta por meio de um URI que contém um número de versão, como https://adventure-works.com/v2/customers/3: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}}

Este mecanismo de controlo de versões é muito simples, mas precisa que o serviço encaminhe o pedido para o ponto final adequado.This versioning mechanism is very simple but depends on the server routing the request to the appropriate endpoint. No entanto, pode tornar-se difícil pois a API Web evoluiu ao longo de várias iterações e o servidor tem de suportar um determinado 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, de um ponto de vista purista, as aplicações cliente estão sempre a obter os mesmos dados (cliente 3), pelo que o URI acaba por não ser realmente diferente independentemente 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. Este esquema também complica a implementação de HATEOAS, uma vez que todas as ligações têm de incluir o número da versão nos seus URIs.This scheme also complicates implementation of HATEOAS as all links will need to include the version number in their URIs.

Controlo de versões 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 caracteres de consulta anexada à 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 da versão deverá ser predefinido para um valor significativo, tal como 1, se for omitido por aplicações cliente mais antigas.The version parameter should default to a meaningful value such as 1 if it is omitted by older client applications.

Esta abordagem tem a vantagem semântica de que o mesmo recurso é obtido sempre pelo mesmo URI, mas depende do código que processa o pedido para analisar a cadeia de consulta e o envio da resposta HTTP adequada.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. Esta abordagem também sofre das mesmas complicações de implementação HATEOAS que o mecanismo de controlo de versões do URI.This approach also suffers from the same complications for implementing HATEOAS as the URI versioning mechanism.

Nota

Alguns browsers e proxies Web mais antigos não colocarão em cache respostas de pedidos que incluem uma cadeia de consulta no URI,Some older web browsers and web proxies will not cache responses for requests that include a query string in the URI. Isso pode prejudicar o desempenho de aplicativos Web que usam uma API da Web e que são executados em 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.

Controlo de versões do cabeçalhoHeader versioning

Ao invés de anexar o número da versão como um parâmetro da cadeia de consulta, 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. Esta abordagem requer que a aplicação cliente adicione o cabeçalho adequado a todos os pedidos, embora o código de processamento do pedido do cliente pudesse utilizar um valor predefinido (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 usam um cabeçalho personalizado chamado cabeçalho personalizado.The following examples use a custom header named Custom-Header. O valor deste cabeçalho indica a versão da API 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}}

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

Controlo de versões do tipo de suporteMedia type versioning

Quando uma aplicação cliente envia um pedido HTTP GET para um servidor Web, este deve definir o formato do conteúdo que pode processar com um cabeçalho Accept, conforme descrito anteriormente nestas orientações.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, o objetivo do cabeçalho Accept consiste em permitir que a aplicação cliente especifique se o corpo da resposta deve ser XML, JSON ou outro formato comum que o cliente pode 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 os tipos de suportes personalizados que incluem informações que permitem à aplicação cliente indicar a versão de um recurso do qual está à espera.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 seguinte mostra um pedido 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 este deve devolver a versão 1 do recurso, enquanto o elemento json especifica que o formato do corpo de 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 a processar o pedido é responsável por processar o cabeçalho Accept e respeitar o mesmo o mais possível (a aplicação cliente pode especificar vários formatos no cabeçalho Accept e, nesse caso, o servidor Web pode escolher o formato mais adequado para o corpo da 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 com 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 todos os tipos conhecidos de suporte, o servidor Web poderá gerar uma mensagem de resposta HTTP 406 (Não Aceitável) ou devolver uma mensagem com um tipo de suporte predefinido.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.

Esta abordagem é possivelmente a mais pura dos mecanismos de controlo de versões e presta-se naturalmente a HATEOAS, que pode incluir o tipo de MIME de dados relacionados em ligações 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.

Nota

Quando seleciona uma estratégia de controlo de versões, deve também considerar as implicações no desempenho, especialmente a colocação 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 controlo de versões do URI e os esquemas de controlo de versões da cadeia de consulta são compatíveis com a cache, assim como a mesma combinação de cadeia de consulta/URI se refere sempre 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.

Geralmente, o controlo de versões do Cabeçalho e os mecanismos de controlo de versões do Tipo de Suporte precisa de uma 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. Num ambiente em grande escala, quando muitos clientes utilizam versões diferentes de uma API Web, tal pode resultar numa quantidade significativa de dados duplicados em 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. Este problema poderá agravar-se se uma aplicação cliente comunicar com um servidor Web através de um proxy que implementa a colocação em cache e que apenas reencaminha um pedido para o servidor Web se este não detiver atualmente uma cópia dos dados solicitados na respetiva 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.

Iniciativa Open APIOpen API Initiative

A Iniciativa Open API foi criada por um consórcio da indústria para uniformizar as descrições da API REST entre os fornecedores.The Open API Initiative was created by an industry consortium to standardize REST API descriptions across vendors. Como parte desta iniciativa, a especificação do Swagger 2.0 foi renomeada Especificação OpenAPI (OAS) e colocada sob a Iniciativa Open API.As part of this initiative, the Swagger 2.0 specification was renamed the OpenAPI Specification (OAS) and brought under the Open API Initiative.

Pode querer adotar a OpenAPI para as suas APIs Web.You may want to adopt OpenAPI for your web APIs. Alguns pontos a considerar:Some points to consider:

  • A Especificação OpenAPI inclui um conjunto de diretrizes opinativas sobre como uma API Rest deve ser concebida.The OpenAPI Specification comes with a set of opinionated guidelines on how a REST API should be designed. Esta possui vantagens relativamente à interoperabilidade, mas requer mais atenção aquando da conceção da API para que esteja em conformidade 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, ao invés de uma abordagem de primeira implementação.OpenAPI promotes a contract-first approach, rather than an implementation-first approach. Primeiro contrato significa criar o contrato da API (a interface) e, em seguida, escrever 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 Swagger podem gerar bibliotecas de clientes ou documentação para contratos de API.Tools like Swagger can generate client libraries or documentation from API contracts. Por exemplo, consulte ASP.NET Web API páginas de ajuda usando o Swagger.For example, see ASP.NET Web API help pages using Swagger.

Mais informaçõesMore information