API Guideline

Objetivo

O objetivo deste guia é fornecer orientação sobre a construção de microservices REST HTTP APIs, detalhando as convenções de melhores práticas sãs, mais importante ainda, a razão pela qual devemos utilizá-los.

Estas convenções não são inventadas. São obtidas principalmente a partir de normas de código aberto e normas comunitárias, e o mais importante, devem ser de autoria, propriedade e dos programadores que as utilizam.

Se as convenções não forem geridas cuidadosamente e implementadas de forma consistente, os custos de integração e manutenção podem crescer exponencialmente à medida que os microserviços proliferam. As normas podem e devem ser alavancadas para mitigar esta sobrecarga, estabelecendo expectativas para todos os novos serviços antes do tempo, tanto intuitiva como programática.

Nosso objetivo é estabelecer um conjunto de convenções e normas simples que
facilitem o desenvolvimento e integração dos microservices. Se implementadas
corretamente, estas diretrizes devem tornar o desenvolvimento mais
rápido
e melhorar o nosso fit com o mercado empresarial.

Vocabulário

Cada diretriz descreve ou uma boa ou má prática, e todas têm uma apresentação consistente.

A redação de cada diretriz indica a força da recomendação.

Fazer é uma recomendação que deve ser sempre seguida. Sempre pode ser um pouco forte demais de uma palavra. Diretrizes que literalmente devem ser sempre seguidas são extremamente raras. Por outro lado, precisamos de um caso realmente incomum para quebrar uma diretriz deste guia.

Considerar as diretrizes geralmente devem ser seguidas. Se você entender completamente o significado por trás da diretriz e tiver uma boa razão para se desviar, então o faça. Por favor, esforce-se para ser consistente.

Evitar indica algo que quase nunca devemos fazer.

Escopo

Estas diretrizes são aplicáveis a qualquer REST HTTP API exposta publicamente. As APIs privadas e internas DEVEM seguir estas diretrizes, até porque os serviços internos são freqüentemente expostos publicamente mais tarde em seus ciclos de vida. A consistência é valiosa não apenas para clientes externos e aplicações front-end, mas também para consumidores de serviços internos, e estas diretrizes oferecem melhores práticas úteis para qualquer serviço.

Há razões legítimas para isenções a estas diretrizes. Um serviço REST que implementa ou deve interoperar com alguma API definida externamente deve ser compatível com essa API, e não necessariamente com estas diretrizes. Alguns serviços PODEM também têm necessidades especiais de desempenho que requerem um formato diferente, tal como um protocolo binário.

Serviços existentes

Os serviços que antes destas diretrizes DEVERÃO tornar-se compatíveis no próximo lançamento da versão, que incorpora uma mudança radical. Os proprietários de serviços devem desenvolver uma estratégia para colocar seus serviços em conformidade na próxima versão principal do serviço ou antes dela.

Os serviços obsoletos ou depreciados DEVERÃO tornar-se conformes se sua utilização continuar mais de 12 meses após a ratificação destas diretrizes.

Design Principles

Se alguma vez estivermos em dúvida sobre um projeto API ou escolha de implementação, que estes Princípios de Projeto nos ajudem a tomar a decisão correta.

  1. Build for the consumer. 
    Os APIs não existem para seu próprio bem, e quase nunca são o ponto de entrada para os usuários finais. Esteja ciente de quais aplicações estarão consumindo nossos serviços e saia do seu caminho para atender às suas necessidades.
  2. Convention over configuration 
    Nossas APIs devem ser intuitivas, e devem aderir e implementar padrões comunitários sempre que possível. A solução de problemas está no centro do desenvolvimento, e é também a grande despesa. Evite implementar soluções personalizadas para problemas que outros já resolveram, e ao fazê-lo, evitaremos criar novos problemas de nosso próprio projeto para consumidores de APIs e mantenedores de base de código.
  3. Optimize close to the metal 
    Desde a autorização e serialização até a filtragem e classificação, ganharemos maior eficiência quanto mais próximos estivermos do banco de dados. Tenha isto em mente ao construir APIs multi layer e dependentes de serviço.

Arquetipos

Ao modelar os recursos de uma API, podemos começar com alguns arquétipos básicos de recursos. Como os padrões de projeto, os arquétipos de recursos nos ajudam a comunicar consistentemente as estruturas e comportamentos que são comumente encontrados nos projetos REST API. Um REST API é composto de quatro arquétipos de recursos distintos: docroot, resource, collection, e controller.

Cada um destes arquétipos de recursos é descrito nas subseções que se seguem.

Docroot

O recurso raiz de um API REST é comumente referido como docroot, também conhecido como documento de referência, e é tipicamente o ponto de entrada anunciado para um API.

O exemplo URI abaixo identifica o docroot para um API Cobli REST:

https://api.cobli.co

Ao determinar a estrutura URL de uma API, é útil considerar que todos os seus recursos existem em um único documento de referência no qual cada recurso é endereçável em um caminho único. Os recursos são agrupados por tipo no nível superior deste documento. Os recursos individuais são agrupados por ID dentro dessas coleções digitadas. Atributos e links dentro de recursos individuais são endereçáveis de forma única de acordo com a estrutura de objetos de recursos descrita acima.

Este conceito de documento de referência é usado para determinar as URLs apropriadas para os recursos, bem como suas relações. É importante entender que este documento de referência difere ligeiramente em estrutura dos documentos usados para transportar recursos devido a diferentes objetivos e restrições. Por exemplo, as coleções no documento de referência são representadas como conjuntos porque os membros devem ser endereçáveis por identificação, enquanto as coleções são representadas como conjuntos em documentos de transporte porque a ordem é significativa.

Recurso

Um recurso é um conceito singular que se assemelha a uma instância de objeto ou a um registro de banco de dados. A representação do estado de um recurso normalmente inclui tanto campos com valores como ligações a outros recursos relacionados. Com seu campo fundamental e estrutura baseada em links, o tipo de recurso é o tipo de base conceitual dos outros arquétipos de recursos. Em outras palavras, os três outros arquétipos de recursos podem ser vistos como especializações do arquétipo de recurso.

Cada URI abaixo identifica um recurso:

https://api.cobli.co/public/v1/devices/245743
https://api.cobli.co/public/v2/groups/94edc37a-77e6-47ee-8364-0cdaad7e200c
https://api.cobli.co/public/v1/vehicles

Um documento pode ter recursos infantis, também conhecidos como recursos aninhados, que representam seus conceitos subordinados específicos.

Cada URI abaixo identifica um recurso aninhado:

https://api.cobli.co/public/v2/devices/4532256922/telemetry
https://api.cobli.co/public/v1/drivers/014f9dc9-f2ef-4a5e-b66c-371fb5ee1c6/score

Collection

Uma collection é um diretório de recursos gerenciado pelo servidor. Os clientes podem propor novos recursos para serem adicionados a uma coleção. Entretanto, cabe à collection optar por criar um novo recurso, ou não. Um recurso de collection escolhe o que quer conter e também decide os URIs de cada recurso contido. As collections também podem ser aninhadas.

Cada URI abaixo identifica um recurso de coleta:

https://api.cobli.co/public/v1/drivers
https://api.cobli.co/public/v1/groups
https://api.cobli.co/public/v2/devices/4532256922/telemetry

Controller

Um controller ou controlador, modela um conceito de procedimento. Os controladores são como funções executáveis, com parâmetros e valores de retorno; entradas e saídas.

Como uma aplicação web tradicional que utiliza formulários HTML, uma API REST depende de controladores para executar ações específicas da aplicação que não podem ser logicamente mapeadas para um dos métodos padrão (criar, recuperar, atualizar e excluir, comumente chamado de "CRUD"). Consulte a seção Métodos abaixo para obter mais detalhes.

Os nomes dos controladores normalmente aparecem como o último segmento em um caminho URI, sem recursos infantis para segui-los na hierarquia. O exemplo abaixo mostra um recurso controlador que permite a um cliente reenviar um alerta a um usuário:

POST /alerts/245743/resend

Nota: Os pontos finais do controlador são excepcionalmente raros nas modernas APIs REST. Se nos encontrarmos implementando mais de dois pontos finais de controladores, pode valer a pena repensar nosso projeto de API.

Convenção de nomes

Fazer nomes de membros iniciais e finais com os caracteres "a-z" (U+0061 a U+007A).

Limite os nomes dos membros aos caracteres "a-z" (U+0061 a U+007A), "0-9" (U+0030 a U+0039), e hífen menos (U+002D HYPHEN-MINUS, "-") como separador entre múltiplas palavras.

Os caracteres permitidos e recomendados para nomeação segura de membros, objetos de resposta e atributos são definidos como parte da Especificação API do JSON.

http://jsonapi.org/format/#document-member-names

Estrutura de URL

Construa URLs API que sejam fáceis de ler para humanos e para aplicações a serem construídas.

Faça substantivos de nomes de recursos com plurals fáceis e convencionais (isto é, acrescente um "s").

Evitar o ninho de relações de recursos infantis mais de uma vez. Em vez disso, prefira localizar os recursos no caminho raiz.

Estruturas de URLs legíveis por humanos facilitam a descoberta e facilitam a adoção entre plataformas sem exigir uma biblioteca de clientes de peso pesado ou de idioma específico.

Um exemplo de um URL bem estruturado é:

https://api.cobli.co/public/v1/people/jdoe

Um exemplo de URL que é NÃO AMIGÁVEL:

https://api.cobli.co/public/v1/EWS/OData/Users('[email protected]')/Pastas('AAMkADdiYzI1MjUxAAAAAACzMsPHYH6HQoSwfdpDx-2bAAAA=')

O uso de URLs como parâmetros é um padrão de projeto comum. Os serviços PODEM utilizar URLs como valores. Por exemplo, o seguinte é aceitável:

https://api.cobli.co/public/v1/images?url=https://cobli.co/products/cobli-cam

Em modelos de dados com relacionamentos de recursos pai/filho aninhados, os caminhos podem tornar-se profundamente aninhados se você não for cuidadoso. As coleções relacionadas devem ser aninhadas no máximo a um nível de profundidade.

Não faça isso:

/orgs/{org_id}/apps/{app_id}/dynos/{dyno_id}

Limitar a profundidade de aninhamento, preferindo localizar os recursos no caminho de raiz. Usar o ninho para indicar coleções escopadas. Por exemplo, para o caso acima, onde um "não" pertence a um "tampão", que pertence a um "org", esta estrutura API é preferível:

/orgs/{org_id}
/orgs/{org_id}/apps
/apps/{app_id}
/apps/{app_id}/dynos
/dynos/{dyno_id}

URLs de relacionamento e URLs de recursos relacionados

Siga as diretrizes de relacionamento e URLs de recursos relacionados abaixo, se nossa API suportar URLs de relacionamento e/ou URLs de recursos relacionados.

Considere formar um URL de recurso relacionado anexando o nome do relacionamento ao URL do recurso.

Considere formar um URL de relacionamento anexando /relacionamentos/ e o nome do relacionamento com o URL do recurso.

Como descrito na JSON API Specification, há duas URLs que podem ser expostas para cada relação:

  • URL do recurso relacionado*** - uma URL para o(s) recurso(s) relacionado(s), que é identificada com a chave relacionada dentro do objeto de links de um relacionamento. Quando buscado, ele retorna o(s) recurso(s) relacionado(s) como os dados primários da resposta.
  • URL*** - um URL para o próprio relacionamento, que é identificado com a chave própria no objeto de links de um relacionamento. Este URL permite que o cliente manipule diretamente o relacionamento. Por exemplo, ela permitiria que um cliente removesse um autor de um post sem apagar o recurso de pessoas em si.

Por exemplo, a URL para os comentários de uma foto será:

/photos/1/comments

E a URL para o fotógrafo de uma foto será:

/photos/1/photographer

A relação de "comentários" de uma foto terá a URL:

/photos/1/relationships/comments

E a relação fotógrafo de uma foto terá a URL:

/photos/1/relationships/photographer

Identificador Canônico

Exponha uma URL contendo um identificador estável e único para todo e qualquer recurso que possa ser movido ou renomeado.

Considere expor uma URL contendo um identificador estável e único para todos os recursos.

Considere o uso de um GUID como o identificador estável para os recursos, quando apropriado (por exemplo, quando respaldado por um banco de dados não-relacional).

Será necessário interagir com o serviço para obter uma URL estável do nome amigável do recurso, como no caso do atalho utilizado por algumas aplicações.

Um exemplo de uma URL contendo um nome amigável é:

https://api.cobli.co/public/v1/people/[email protected]

E um exemplo de um URL contendo um identificador canônico é:

https://api.cobli.co/public/v1/people/10f7a66b-083d-401f-93e7-dffc172c6fea

Controladores de URL e Verbos

Evite usar os métodos ou verbos CRUD HTTP (por exemplo, GET, POST, PUT, DELETE, etc.) nos caminhos URL.

URIs NÃO DEVE ser utilizada para indicar que uma função CRUD.

URIs DEVEM ser utilizados para identificar recursos de forma única, e eles DEVEM ser nomeados como descrito nas seções abaixo. Os métodos e verbos HTTP DEVEM ser utilizados para indicar qual função CRUD é executada.

Por exemplo, este projeto de interação API é válido:

DELETE / users/1234

Enquanto os seguintes anti-padrões exemplificam o que não se deve fazer:

GET /deleteUser?id=1234
GET /deleteUser/1234
DELETE /deleteUser/1234
POST /users/1234/delete

Tamanho URL

O formato de mensagem HTTP 1.1, definido na IETF RFC 7230 Seção 3.1.1, não define nenhum limite de comprimento na Request Line, que inclui a URL de destino.

Responda com um código de status 414 (URI Too Long) a qualquer solicitação com um URI alvo mais longo do que desejamos analisar.

Considere fazer acomodações para os clientes que desejamos apoiar ao implementar um serviço que gera URLs com mais de 2.083 caracteres.

Nota: Algumas stacks de tecnologia têm limites de URL rígidos e ajustáveis, portanto tenha isso em mente ao projetar serviços com URLs mais longas do que o habitual.

Verbos HTTP

Sempre que possível, utilize os verbos HTTP apropriados para operações API.

Respeite a idempotência operacional (veja a tabela abaixo).

VerboDescrição de usoÉ idempotente
GETDevolver o valor atual de um objeto.SIM
PUTSubstituir um objeto, ou criar um objeto nomeado, quando aplicável.SIM
DELETEApaga um objeto.SIM
POSTCriar um novo objeto com base nos dados fornecidos, ou submeter um comando.NÃO
HEADRetornar metadados de um objeto para uma resposta GET. Recursos que suportam o método GET PODEM também suportar o método HEAD.SIM
PATCHAplicar uma atualização parcial a um objeto.NÃO

Abaixo está uma lista de métodos REST HTTP APIs / serviços PODEM ter suporte. Nem todos os recursos suportarão todos os métodos, mas todos os recursos utilizando um ou mais dos métodos abaixo DEVEM estar de acordo com sua utilização.

DELETE

Considere apoiar a eliminação de múltiplos recursos de uma só vez através de uma filtragem estilo GET de IDs de recursos (por exemplo, /users?id=[20,30,40,60,90]).

Considere apoiar a eliminação de múltiplos recursos ao mesmo tempo através de uma lista separada por vírgula de IDs de recursos (por exemplo, /users/20,30,40,60,90).

A eliminação de recursos é definida como parte da Especificação API JSON API. Veja o link abaixo para os requisitos completos de implementação do DELETE e detalhes de especificação.

http://jsonapi.org/format/#crud-deleting

GET

A busca de recursos é definida como parte da Especificação API JSON API. Veja o link abaixo para os requisitos completos de implementação do GET e detalhes de especificação.

http://jsonapi.org/format/#fetching-resources

PATCH

PATCH foi padronizado pela IETF como o método utilizado para atualizar incrementalmente um objeto existente (ver [IETF RFC 5789] (https://tools.ietf.org/html/rfc5789)).

Apoiar a criação de recursos usando o PATCH, se nosso serviço NÃO SUPORTAR um UPSERT semântico.

Responda com um código de erro HTTP 404 Not found a um pedido de PATCH contra um recurso que não existe, se nosso serviço NÃO SUPORTA um UPSERT semântico.

Considere suportar a semântica UPSERT em serviços que permitam aos chamadores especificar valores chave na criação.

Considere apoiar atualizações de múltiplos recursos ao mesmo tempo através de uma filtragem estilo GET de IDs de recursos (por exemplo, /users?id=[20,30,40,60,90]).

Considere apoiar atualizações de múltiplos recursos ao mesmo tempo através de uma lista separada por vírgula de IDs de recursos (por exemplo, /users/20,30,40,60,90).

Evite tratar um pedido de PATCH como um encarte se ele contiver um header If-Match.

Evite tratar um pedido de PATCH como uma atualização se ele contiver um header If-None-Match com um valor de *.

Na semântica UPSERT, uma chamada PATCH para um recurso inexistente é tratada pelo servidor como uma criação, e uma chamada PATCH para um recurso existente é tratada como uma atualização. Para garantir que uma solicitação de atualização não seja tratada como uma criação ou vice-versa, o cliente PODE especificar nos headers HTTP uma pré-condição na solicitação.

A atualização de recursos é definida como parte da Especificação da API JSON API. Veja o link abaixo para os requisitos completos de implementação PATCH e detalhes de especificação.

http://jsonapi.org/format/#crud-updating

POST

Suportar o header de resposta de Location para especificar a localização de qualquer recurso criado que não tenha sido explicitamente nomeado, através do header de Location.

Considere devolver metadados completos para o item criado na resposta.

Como exemplo, imagine um serviço que permita a criação de servidores hospedados, que serão nomeados pelo serviço:

POST https://api.cobli.co/public/v1/device/2832732/telemetry

A resposta deve ser parecida:

201 Created
Location: https://api.cobli.co/public/v1/device/2832732/telemetry/telemetry321

Onde telemetry321 é o ID da Telemetria alocada por serviço.

A criação de recursos é definida como parte da Especificação API JSON API. Veja o link abaixo para os requisitos completos de implementação do POST e detalhes de especificação.

http://jsonapi.org/format/#crud-creating

PUT

Use semântica de substituição (isto é, após o PUT, as propriedades do recurso DEVEM corresponder ao que foi fornecido no pedido, incluindo a eliminação de quaisquer propriedades existentes que não são fornecidas), para qualquer serviço que suporte pedidos de PUT.

Considere apoiar pedidos de PUT para atualizar (via semântica de substituição) os recursos existentes.

Como o PUT é definido como uma substituição completa do conteúdo, é perigoso para os clientes usar o PUT para modificar dados. Os clientes que não entendem (e, portanto, ignoram) as propriedades de um recurso não são capazes de fornecê-las em um PUT ao tentar atualizar um recurso, portanto tais propriedades PODEM são inadvertidamente removidas.

Consulte a seção PATCH acima para obter mais detalhes.

Request Headers

Suportar os Request Headers de forma consistente em todos os endpoints e recursos.

Considere suportar cada um dos Request Headers definidos na tabela a seguir.

A seguinte tabela de Request Headers abaixo DEVERÁ ser suportada por REST HTTP APIs e serviços. O suporte a todos esses headers não é obrigatório, mas se forem suportados, DEVEM ser suportados de forma consistente.

Todos os valores de header DEVEM seguir as regras de sintaxe estabelecidas nas especificações abaixo, onde cada campo de header é definido. Muitos headers HTTP são definidos em IETF RFC 7231, porém uma lista completa de headers aprovados pode ser encontrada no IANA Header Registry.

HeaderTipoDescrição
AuthorizationStringHeader de autorização de uma request
DateDateTimestamp do pedido, com base no relógio do cliente, no formato de data e hora RFC 5322. O servidor NÃO DEVERÁ fazer nenhuma suposição sobre a precisão do relógio do cliente. Este header PODE ser incluído na solicitação, mas DEVE estar neste formato quando fornecido. O Horário Médio de Greenwich (GMT) DEVE ser usado como referência de fuso horário para este header quando ele for fornecido. Por exemplo, o horário de Greenwich: Qua, 24 de agosto de 2016 18:41:30 GMT. Observe que o GMT é exatamente igual ao UTC (Tempo Universal Coordenado) para este fim.
AcceptContent typeA requisição pode ser feita com os seguintes tipos de entrada.

Exemplo:
• application/json; version=1.0
• application/vnd.api+json; version=1.0
• application/xml; version=1.0
• text/javascript; version=1.0

De acordo com as diretrizes HTTP, isto é apenas uma dica e as respostas PODEM ter um tipo de conteúdo diferente, como um blob fetch onde uma resposta bem sucedida será apenas o fluxo de blob como a carga útil. Deve incluir também a versão API solicitada.
Accep-EncodingGzip, defateDEVERÁ suportar codificação GZIP e DEFLATE, quando aplicável. Para recursos muito grandes, os serviços `PODEM ignorar e retornar dados não compactados.
Accept-Languageen, es, pt-BR, etc.Especifica o idioma preferido para a resposta. Os serviços não são necessários para suportar isto, mas se um serviço suporta localização, DEVE fazê-lo através do header Accept-Language.
Accept-CharsetUTF-8Padrão é UTF-8, mas alguns serviços pode lidar com ISO-8859-1.
Content-Typeapplication/jsonTipo de conteúdo do corpo de solicitação (PUT/POST/PATCH)

Response Headers

Devolva todos os Response Headers definidos na tabela a seguir, exceto onde indicado na coluna necessário.

HeaderRequeridoDescrição
DateTodas as respostasA resposta foi processada, com base no relógio do servidor, no formato de data e hora RFC 5322. Este header DEVE ser incluído na resposta. A hora média de Greenwich (GMT) DEVE ser usada como referência de fuso horário para este header. Por exemplo: Qua, 24 de august de 2016 18:41:30 GMT. Observe que o GMT é exatamente igual ao UTC (Tempo Universal Coordenado) para este fim.
Content-TypeTodas as respostasContent type.
Content-EncodingTodas as respostasGZIP ou DEFLATE, conforme o que for apropriado.
ETagQuando solicitado, o recurso tem uma etiqueta de entidade.O campo de header de resposta ETag fornece o valor atual da etiqueta da entidade para a variante solicitada. Usado com If-Match, If-None-Match e If-Range para implementar um controle otimista da concorrência.

Custom Headers

Evite custom header obrigatórios para a operação básica de um API.

Algumas das diretrizes deste documento prescrevem o uso de headers HTTP específicos do domínio. Além disso, alguns serviços PODEM expor funcionalidades extras através de headers HTTP personalizados. As seguintes diretrizes ajudam a manter a consistência na utilização de headers personalizados.

Os headers customizados DEVEM ter um de dois formatos:

  1. Um formato genérico para headers IANA registrados como provisórios (ver [IETF RFC 3864][rfc-3864]).
  2. Um formato com escopo para headers muito específico de uso para registro.

Formatação da resposta

Para que as organizações tenham uma plataforma de sucesso, elas devem servir os dados de forma consistente e em formatos que os desenvolvedores estejam acostumados a usar, permitindo que os desenvolvedores lidem com respostas com código comum.

Regras de Ouro

Se alguma vez estivermos em dúvida sobre uma decisão de formatação API, que estas Regras de Ouro nos ajudem a tomar a decisão correta.

  1. Flat é melhor do que aninhado.
  2. Simples é melhor do que complexo.
  3. As strings são melhores que os números.
  4. A coerência é melhor do que a personalização.

Noções básicas

Forneça JSON como a codificação de resposta API padrão.

Fazer camelCase JSON nomes de propriedade.

Faça a formatação padrão da resposta "aplicação/json" se não for fornecido o header Accept.

Considere apoiar formatos alternativos de resposta solicitados pelo cliente usando o header Accept.

Considere retornar um código de erro HTTP não aceitável 406 ao rejeitar uma solicitação de cliente devido a um header de solicitação de aceitação incompatível ou malformado.

Em HTTP, o formato de resposta DEVE ser solicitado pelo cliente utilizando o header Accept. Esta é uma dica, e o servidor PODE ignorar se optar por fazê-lo, mesmo que isto não seja típico de servidores bem-comportados. Os clientes PODEM enviar vários headers Accept e o serviço PODE escolher um deles.

O formato de resposta padrão (sem header Accept fornecido) DEVERÁ ser application/json, e todos os serviços DEVEM suportar application/json.

Formato da data

6: Esta seção é um toco. Pense em expandir.

Use o formato de data RFC3339, a menos que haja razões muito convincentes para fazer o contrário.

O RFC 3339 fornece uma visão geral dos formatos recomendados.

Especificação JSON API

Siga as diretrizes de formatação da Especificação JSON API, detalhadas abaixo, o mais próximo possível.

Responda às solicitações com application/json Aceite headers com dados em formato JSON API e um header application/vnd.json-api Content-Type, se nenhum outro formato JSON não recomendado for suportado pela API.

Considere apoiar formatos alternativos de resposta JSON, conforme a necessidade da aplicação ou requisitos comerciais.

JSON API é uma especificação de como um cliente deve solicitar que os recursos sejam buscados ou modificados, e como um servidor deve responder a essas solicitações.

A familiaridade com a especificação JSON API é fortemente encorajada*.

Nós DEVEMOS modelar nossas estruturas de resposta API no JSON API o mais próximo possível. A especificação completa juntamente com exemplos e bibliotecas populares podem ser referenciadas no link abaixo.

http://jsonapi.org

Booleans, NULLs e Stringification

Formatar todos os tipos de campos binários como booleano.

Formatar todos os números como strings no corpo de resposta, incluindo IDs de recursos numéricos e chaves primárias.

Formatar booleans como booleans (sem strings), e nulos como nulos (sem strings).

Devolver NULL para campos sem valor, quando um valor tiver sido eliminado e quando um valor nunca tiver existido.

Devolver NULL para valores de campo booleano, número e string inexistentes.

Evite representar campos de string sem valor como "". Retornar um valor NULL (eles significam duas coisas diferentes).

Evite retornar NULL para matrizes vazias como conjuntos. Em vez disso, devolva um conjunto literalmente vazio ([]) e/ou conjunto ({}).

Evite datilografar valores de campo para números. Isto quase nunca é uma boa idéia, pois muitas vezes leva à duplicação, ineficiências ocultas, complexidade de testes e dificuldades do cliente.

Estas diretrizes existem para evitar confusão, minimizar a complexidade e facilitar muito o trabalho dos desenvolvedores da linha de frente.

Lembre-se, um tipo de campo deve ser booleano se seu valor for binário.

Não utilize 0 e 1, não utilize "0" e "1", e não tente encontrar uma solução melhor. Utilize o que já temos: "verdadeiro" e "falso" (o tipo de elenco aqui precisa ser). É universal e objetivo.

Exemplo:

GET /customers/16784

{
  "type": "customers",
  "id": "16784",
  "attributes": {
    "name": "Joe Smith",
    "age": null,
    "relatives": [],
    "address": null
		"isActive": true
  }
}

Nota: "id" é representado como um String.

Muito parecido com a localização de data/hora, fundição de tipo e transformação de tipo só deve acontecer uma vez, e o mais próximo possível do cliente. Confie no cliente para saber como ele quer seus dados formatados, e economize trabalho desnecessário retornando valores de campo como Strings, nativos de JavaScript, sempre que possível.

Filtragem

Reserve o parâmetro de consulta do filtro para ser usado como base para qualquer estratégia de filtragem.

Considere suportar a filtragem de uma coleção de recursos com base em associações, permitindo parâmetros de consulta que combinam o filtro com o nome da associação.

Por exemplo, o seguinte é um pedido para todos os comentários associados a um determinado cargo:

GET /comentários?filter[post]=1 
HTTP/1.1

Vários valores de filtros podem ser combinados em uma lista separada por vírgulas. Por exemplo:

GET /comentários?filter[post]=1,2 
HTTP/1.1

Além disso, vários filtros podem ser aplicados a uma única solicitação:

GET /comentários?filtro[post]=1,2&filtro[autor]=12 
HTTP/1.1

Consulte a seção JSON API Specification section acima para obter todos os requisitos de implementação de filtragem e detalhes de especificação.

http://jsonapi.org/format/#fetching-filtering

Paginação

Considere limitar o número de recursos devolvidos em resposta a um subconjunto ("página") de todo o conjunto disponível.

Considere fornecer links para atravessar um conjunto de dados paginados ("links de paginação").

Aqui está uma ilustração de uma implementação baseada em páginas de links de paginação.

Exemplo de solicitação:

GET /articles?page=3&size=10 
HTTP/1.1

Exemplo de resposta:

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

{   
		"data": [    
						{      
									"type": "articles",      
									"id": "3",      
									"attributes": {        
				   "title": "JSON API paints my bike shed!",
                                    "body": "The shortest article. Ever.",
                                    "created": "2015-05-22T14:56:29.000Z",        
                                    "updated": "2015-05-22T14:56:28.000Z"      
                                 }    
                 }  
            ],  
    "pagination": {    
       "page": 3,   
       "prev": "https://example.com/articles?page[number]=2&page[size]=1",    
       "next": "https://example.com/articles?page[number]=4&page[size]=1"
    }
}

A paginação é definida como parte da Especificação API do JSON. Veja o link abaixo para os requisitos completos de implementação da paginação e detalhes de especificação.

http://jsonapi.org/format/#fetching-pagination

Ordenação

Ordenar os valores NULL como "menos que" valores não NULL, para serviços que suportam a classificação.

Considere suporte a ordenação dos resultados de uma consulta de coleta com base nos valores de propriedade.

A ordenação é definida como parte da Especificação API do JSON. Veja o link abaixo para os requisitos de ordenação completa da implementação e detalhes de especificação.

http://jsonapi.org/format/#fetching-sorting

Monitoramento

Os serviços REST HTTP DEVEM implementar os parâmetros API /healthcheck e /version de acordo com as diretrizes definidas abaixo.

Os parâmetros /debug, /metrics e /status são altamente recomendados.

Health

Responda às solicitações de/para o exame de saúde com um código de status 200 OK.

Responda com um serviço 503 No available para indicar um serviço severamente degradado ou offline.

Evite devolver o corpo vazio na resposta, ou de outra forma complicar em demasia o ponto final/saúde.

Os endpoints /healthcheck são projetados especificamente para balanceadores de carga e soluções de descoberta de serviços. Como tal, eles devem ser extremamente simples, indicando a saúde de um API através de códigos de resposta HTTP.

Um balanceador de carga deve saber se deve manter um serviço no pool ou ejetá-lo após enviar uma solicitação HEAD para o ponto final de saúde do serviço.

Exemplo de solicitação:

HEAD /healthcheck 
HTTP/1.1

Exemplo de resposta:

HTTP/1.1 200 OK
Date: Sat, 10 Sep 2012 20:50:55 GMT
X-API-Version: 1.0

Debug

Desabilitar / depurar o endpoint por padrão.

Exigir DEBUG=true configuração ou variável de ambiente no início da aplicação para habilitar /debugar o ponto final.

Evitar expor / depurar o endpoint em ambientes não desenvolvidos.

Os endpoints /debug são projetados especificamente para uso interno, para expor a configuração sensível, o ambiente e as informações de registro para ajudar no desenvolvimento. Estes pontos finais NÃO são para consumo público, como tal devem ser desativados por padrão, exigindo uma configuração explícita de configuração sem falha ou variável de ambiente para habilitar na inicialização.

As respostas úteis /debug endpoint podem incluir.

  • Uma cópia do package.json.
  • Data do último reinício do serviço.
  • Últimas mensagens de log em nível de depuração.

Métricas

Expor contadores de aplicação e estatísticas através do ponto final /metrics.

Evite calcular métricas difíceis de calcular ou de recursos intensivos.

Os pontos finais /metrics são projetados especificamente para ferramentas de painel de instrumentos e integrações de banco de dados de séries temporais. Um endpoint métrico deve produzir resultados ao vivo e deve ser capaz de servir aplicações a 1 QPS (Queries Per Second) sem qualquer impacto no desempenho da aplicação. Como tal, evite expor métricas difíceis de calcular ou de uso intensivo de recursos, ou se for necessário, faça a média ou o cache delas durante o tempo necessário e nomeie-as de acordo (por exemplo response_time_avg_60_sec).

Respostas úteis `/metrics' de pontos finais podem incluir.

  • Tempo de atividade em segundos.
  • Tempo médio de resposta.
  • Média de QPS no último minuto.
  • Número de 500 erros.

Versão

Responder a solicitações /versão com um objeto JSON descrevendo a versão em execução do serviço especificado nos parâmetros de rota.

Evite obter informações de versões de arquivos em disco, ou outras fontes mutáveis externas ao tempo de execução da aplicação.

Os pontos finais /version são projetados tanto para o consumo humano quanto para a descoberta dinâmica de serviços. As respostas devem ser extremamente simples, indicando a versão de um API e nada mais.

É muito importante garantir que a aplicação retorne a versão em execução da aplicação, e não a versão instalada. Sempre carregue as informações da versão na memória ao iniciar a aplicação, em vez de procurar em qualquer local externo ou mutável.

Exemplo de request:

GET /v1/public/groups 
HTTP/1.1

Exemplo de resposta:

HTTP/1.1 200 OK
Date: Sat, 10 Sep 2012 20:50:55 GMT
X-API-Version: 1.0

{  
		"version": "1.0" 
}

As respostas devem ser extremamente simples, indicando a versão de um API e nada mais.

Versionamento

Exigir que o cliente especifique a versão como parte dos parâmetros do caminho.

A criação de versões e a transição entre versões pode ser um dos aspectos mais desafiadores do projeto e operação de um API. Como tal, o melhor é criar alguns mecanismos para mitigar este ponto de dor desde o início.

Para evitar surpresas e mudanças de quebra para os consumidores de API, é melhor exigir que uma versão seja especificada com todas as solicitações. As versões padrão devem ser evitadas, pois são muito difíceis de serem alteradas no futuro (por projeto, qualquer alteração na versão padrão seria uma alteração de ruptura).

GET /v1/public/groups/ HTTP/1.1
Host: api.cobli.co
Accept: application/json

Breaking Change

As mudanças no contrato de um API são consideradas uma mudança de ruptura. As mudanças que afetam a compatibilidade retroativa de um API são uma mudança de ruptura. Normalmente, a adição de pontos finais, recursos e campos não é considerada uma quebra, enquanto que a modificação ou remoção da mesma é considerada uma quebra.

Exemplos claros de mudanças de quebra:

Deprecation

Devolva sempre a versão API respondendo à solicitação em um header de resposta X-API-Version.

Inclua um header de resposta X-API-Warn quando uma versão API depreciada for solicitada no header de solicitação Accept, ou quando o endpoint for depreciado.

Inclua um aviso no meta membro da resposta do JSON se uma solicitação for feita com campos depreciados ou parâmetros de consulta.

Indicar na documentação API quando as versões API obsoletas chegarem ao fim da vida útil.

Em uma versão API ou cenário de ponto final obsoleto, retornar um header de resposta X-API-Warn com um valor que se parece com este:

AVISO! Você está utilizando uma versão obsoleta desta API. Para informações sobre atualização, veja <{link}>.

Em um campo depreciado ou cenário de parâmetro de consulta, retornar um aviso na "meta" membro da resposta do JSON que se parece com isto:

{  "meta": {    
								"warning": "You are using a deprecated version of this API. For information on upgrading see <{link}>."  
						},  
		"data": {    
									// ...  
						}
}

Onde {link} é um URL para um recurso de documentação API relevante.

A idéia é que esta mensagem apareça nos logs do servidor, esperando que os consumidores de APIs possam atualizar.

Como e Quando para Versão

Aumente o número de versão de um API em resposta a qualquer mudança de interrupção.

Indique o status atual de suporte de cada versão da API, passada e presente, na documentação da API.

Suporta números de versão no formato {majorVersion}.{minorVersion}.

Considere a possibilidade de incrementar um número de versão do API para mudanças sem quebra.

Use um novo número de versão principal para sinalizar que o suporte aos clientes existentes será depreciado no futuro. Ao introduzir uma nova versão principal, os serviços DEVEM proporcionar um claro caminho de atualização para os clientes existentes e desenvolver um plano de desvalorização que seja consistente com as políticas de seu grupo comercial. Os serviços DEVEM utilizar um novo número de versão menor para todas as outras mudanças.

A documentação on-line dos serviços com versão DEVEM indicar o status atual de suporte de cada versão anterior da API.

Grupo de versões

Considere o suporte de versões em grupo em vários microserviços para fornecer aos consumidores multi-API um esquema de versões unificado.

As versões de grupo permitem o agrupamento lógico de pontos finais API sob um moniker de versão comum. Isto permite aos desenvolvedores procurar um único número de versão e usá-lo em vários pontos de extremidade. Os números de versão em grupo são bem conhecidos, e os serviços DEVERIAM rejeitam quaisquer valores não reconhecidos.

Internamente, cada serviço levará uma versão em grupo e mapeará para sua versão Major.Minor apropriada.

O formato da Versão em Grupo é definido como YYYY-MM-DD, por exemplo 2021-12-01 para December 1, 2021. Este formato de versão de data aplica-se somente às Versões em Grupo e NÃO DEVERIA ser utilizado como uma alternativa à Versão Principal. Versões menores.

Os clientes podem especificar tanto a versão de grupo quanto a versão major.minor específica do ponto final.

Por exemplo, a versão menor:

GET /v1/assets/ HTTP/1.1
Host: api.cobli.co
Accept: application/vnd.api+json

Ou de forma equivalente, quando são suportadas Versões de Grupo:

GET /v1/assets/ HTTP/1.1
Host: api.cobli.co
Accept: application/vnd.api+json

Todas as Versões de Grupo suportadas, juntamente com seus status de depreciação e datas de fim de vida, devem ser publicadas e mantidas atualizadas na documentação API pública.

Segurança

Faça aplicar HTTPS (encriptado em TLS) em todos os endpoints, recursos e serviços.

Faça cumprir e exija HTTPS para todos os URLs de retorno de chamada, pontos finais de notificação push e webhook.

CORS

Suportar os headers CORS (Cross Origin Resource Sharing) para todos os APIs voltados para o público.

Considere apoiar uma origem CORS permitida de *, e fazer valer a autorização através de fichas portadoras válidas.

Evite combinar as credenciais do usuário com a validação da origem.

Pode haver exceções para casos especiais.