Tuesday 10 April 2018

Estratégia de versão do restante api


O seu controle de versão da API é errado, razão pela qual eu decidi fazer 3 maneiras erradas diferentes.
No final, eu decidi que a maneira mais justa e equilibrada era irritar todos com igualdade. Claro que eu estou falando sobre o controle de versão da API e não desde o grande & # x201C; tabs versus spaces & # x201D; debate eu vi tantas crenças fortes em campos completamente diferentes.
Isso estava bem. Quando eu construí Eu fui escolhido? (HIBP) no final de novembro, pretendia ser um serviço simples e rápido que algumas pessoas usariam. Eu acho que é justo dizer que os dois primeiros pontos foram alcançados, mas não o último. Não foi & # x201C; alguns & # x201D ;, de fato, no final da primeira semana, foi mais do que o Google Analytics poderia lidar. O objetivo é que você sempre pode prever o futuro quando você escreve sua API e, em algum momento, você pode precisar mudar algo em que as pessoas já dependem.
Mas aqui, o problema & # x2018; Toda vez que você começa a falar sobre qualquer coisa a ver com APIs por HTTP, isso acontece:
Todo o caminho em que você se transforma há diferentes pontos de vista filosóficos em & # x201C; o caminho certo & # x201D; e muito retroceder e avançar no REST, o que é RESTful, o que não é e se importa. Deixe uma conversa sobre as mudanças da API, o impacto no controle de versão, por que há tantas idéias divergentes sobre como deve ser feito e, em última análise, por que nenhuma das palavras é tão importante como realmente conseguir coisas feitas.
Puxando mais dados de violação.
Tendo em mente que a mesma API é usada para o recurso de pesquisa no site e agora também por terceiros que criam tudo, desde aplicativos de smartphones até ferramentas de teste de penetração, a resposta acima funcionou bem no início, mas foi limitada. Por exemplo, essa resposta também não funciona bem:
Por quê? Porque & # x201C; BattlefieldHeroes & # x201D; é Pascal-encapsulado, o que é ótimo para combiná-lo com classes CSS codificadas (embora provavelmente não seja uma boa abordagem de longo prazo) e para ter um & # x201C; stable & # x201D; nome para se referir a (eu ganhei & # x2019; t mudá-lo, mesmo se houver uma segunda violação), mas não é adequado para exibição como título. Tudo isso sai do Azure Table Storage e depois entrei no SQL Azure para extrair dados relacionais que realmente descrevem a violação. Um dos atributos desse armazenamento relacional é o nome que você vê acima.
O que eu realmente queria fazer era algo mais parecido com isto:
Pegue? Para o ponto anterior sobre o nome da infração, esse ainda está lá no atributo de nome, mas agora temos um título também. Isto é o que você mostra para as pessoas & # x2018; & # x201C; Battlefield Heroes & # x201D; & # x2018; Mas, mais importante ainda, se Gawker for repetidamente, eu posso nomear a violação de algo como Gawker2018 e o título pode ser algo amigável ao longo das linhas de & # x201C; Gawker (Syrian Electronic Army Attack) & # x201D ;. Ele segmenta o que é estável e previsível a partir do que não é e significa que as pessoas podem criar dependências, como imagens ou outros recursos no atributo de nome.
Os outros dados devem ser bastante claros: a data da violação, quando foi adicionada ao sistema, o número de contas, a descrição da violação (novamente, isso pode mudar se a verbiagem precisa ser modificada) e & # x201C; DataClasses & # x201D ;. Uma das coisas que muitas pessoas pediram foi uma descrição do que foi comprometido na violação, então agora há um monte de atributos que podem ser adicionados através de uma coleção sobre a violação em si. Eu já mostrando estes abaixo de cada violação na página dos sites Pwned (esta é outra razão pela qual agora posso ajustar algumas das descrições).
Esta é uma mudança radical. Embora o sentimento da API seja o mesmo & # x2018; fornecer um nome de conta, recuperar uma lista de violações & # x2018; não há mais um conjunto de caracteres de violação de nomes de violação. Se eu simplesmente substituísse a API antiga por essa, as coisas iriam quebrar. APIs. Devo. Evoluir.
O software evolui, as APIs devem ser controladas.
Deixe-se ficar claro sobre isso: o mundo continua. A API para o HIBP durou cerca de 2 meses, não porque estava mal concebida, mas porque o serviço tornou-se selvagem, inesperadamente bem sucedido. Eu gosto desse tipo de problema, e você também deveria.
Agora eu tinha uma escolha; Ou eu poderia me contentar com o que eu tinha e privar as pessoas de uma maneira melhor, eu poderia adicionar ao serviço existente de forma não rompente ou eu poderia criar uma nova versão (embora expondo a mesma entidade de uma maneira diferente) e construa da melhor maneira que eu sabia; sem bytes desnecessários, modelados corretamente (até que eu decida que uma nova versão é mais correta) e uma boa representação da entidade que eu finalmente tentarei entrar nos consumidores & # x2019; aplicativos.
Não há nada de errado em apresentar uma nova versão de uma API quando é a coisa mais sensível. Por todos os meios, faça o seu mais difícil para obtê-lo & # x201C; right & # x201D; desde o primeiro dia, mas faça isso com a expectativa de que & # x201C; right & # x201D; é um estado temporário. É por isso que precisamos ser capazes de versão.
Os vários campos de versão.
Certo, então, como é difícil esse negócio de versão? Quero dizer, deve ser um exercício simples, certo? O problema é que ele é muito filosófico, mas, em vez de ficar atolado, por enquanto, deixe-me esboçar as três escolas comuns de pensamento em termos de como elas são praticamente implementadas:
URL: Você simplesmente invade a versão da API no URL, por exemplo: https: // haveibeenpwned / api / v2 / breachedaccount / foo Cabeçalho de solicitação personalizado: Você usa o mesmo URL que antes, mas adicione um cabeçalho como o & # x201C; api - versão: 2 & # x201D; Aceitar cabeçalho: você modifica o cabeçalho de aceitação para especificar a versão, por exemplo & # x201C; Aceitar: application / vnd. haveibeenpwned. v2 + json & # x201D;
Houve muitas, muitas coisas escritas sobre isso e eu vou ligar para elas no final da publicação, mas aqui a versão abreviada é:
Os URLs sugam porque devem representar a entidade: na verdade eu realmente concordo com isso na medida em que a entidade I & # x2019; m recuperando é uma conta quebrada, e não uma versão da conta violada. Semanticamente, não é realmente correto, mas sim, é fácil de usar! Os cabeçalhos de solicitação personalizados sugam porque ele não é realmente uma maneira semântica de descrever o recurso: a especificação HTTP nos dá um meio de solicitar a natureza que nós gostamos do recurso representado por meio do cabeçalho de aceitação, por que reproduzir esta? Aceite cabeçalhos sugam porque eles são mais difíceis de testar: eu não posso mais apenas dar a alguém um URL e dizer & # x201C; Aqui, clique neste & # x201D; antes eles precisam construir cuidadosamente a solicitação e configurar o cabeçalho de aceitação adequadamente .
Os vários argumentos para e contra cada abordagem tendem a passar de & # x201C; Este é o & # x2018; right & # x2019; maneira de fazê-lo, mas é menos prático & # x201D; através de & # x201C; Esta é a maneira mais fácil de criar algo consumível o que, portanto, o torna & # x2018; direito & # x2019; & # x201D ;. Há muita discussão sobre hipermídia, negociação de conteúdo, o que é & # x201C; REST & # x201D; e todas as outras questões. Infelizmente, isso muitas vezes se torna filosófico e perde a visão do objetivo real: construir um software que funcione e particularmente para uma API, tornando-o facilmente consumível.
É sobre ter um contrato estável, estúpido!
Mais importante do que todo o desencadeamento e delírio sobre fazê-lo dessa maneira ou dessa forma é dar às pessoas estabilidade. Se eles investem o seu código de escrita de esforço duro para consumir a sua API, então você melhorará muito, não vá e quebre-a mais na linha.
Honestamente, os debates sobre o que é & # x201C; RESTful & # x201D; versus o que não é como se o próprio termo ditar seu sucesso é apenas louco. Transforme essa discussão em & # x201C; Aqui estão os motivos práticos pelos quais isso faz sentido e isso é o que pode acontecer se você não fizer isso e # x201D ;, e eu e todos os ouvidos. O problema é que até mesmo as vozes da razão nas discussões barulhentas deixam dúvidas sobre o que realmente é a melhor abordagem e, portanto, eu alcancei um compromisso & # x2026;
Aqui estão 3 maneiras erradas de consumir a API HIBP que você pode escolher agora.
Ok, agora que nós estabelecemos claramente o que você faz é errado, eu gostaria de lhe dar a escolha de escolher entre qualquer uma das 3 maneiras erradas. Aguarde & # x2018; o que?! É assim: no entanto, implemento a API, será muito difícil de consumir, muito acadêmico, muito provável que falhe no proxy ou algo como algo. Ao invés de escolher 1 maneira errada, eu decidi você dar todas as 3 maneiras erradas e você pode escolher aquele que é o menos errado para você.
Wrong way 2 - cabeçalho de solicitação personalizado:
Inevitavelmente, alguém me dirá que fornecer 3 maneiras erradas é a coisa errada a fazer. Won & # x2019; t significa mais código kludge para manter? Não, simplesmente significa que a implementação da API da Web subjacente é decorada com dois atributos:
O primeiro é simplesmente uma restrição de roteamento que implementa RouteFactoryAttribute. Eu passo na rota e passa na versão que pode mapear para essa rota, então a implementação procura a presença de uma & # x201C; api-version & # x201D; cabeçalho ou um cabeçalho de aceitação correspondente a este padrão:
Se a versão especificada em qualquer uma dessas combina com a especificada na restrição de roteamento, então esse é o método que será invocado. Esta é uma adaptação simples desta amostra no CodePlex.
O segundo atributo que decora o método GetV2 acima vem com cortesia da Web API 2 e o recurso de roteamento de atributos. Claro que sempre poderíamos fazer o roteamento na API da Web, mas geralmente foi definido globalmente. O roteamento de atributos como esse traz a definição da rota para o contexto onde ela é aplicada e torna mais fácil ver qual ação do controlador vai ser chamada por qual rota. Isso também significa que as implementações para todas as 3 maneiras erradas de chamar a API se juntam em um local limpo.
Então, em suma, não, isso não cria muito kludge e é muito fácil de manter. Cada uma das 3 abordagens retornará exatamente o mesmo resultado e, o mais importante, eles permanecerão estáveis ​​e ganharão mudar em qualquer maneira de quebrar e, no final do dia, isso é o máximo coisa importante, independentemente da opção que você escolher. A implementação inteira agora também está claramente documentada na página API do site.
Mas e se você não especificar uma versão?
Você conhece o pouco onde eu disse que você pode quebrar o que já existe? Sim, então isso significa que se você fizer o que faz agora & # x2018; não especifique uma versão & # x2018; então você obtém o que você recebe agora. Em outras palavras, nenhum pedido para uma versão específica significa que você obteve a versão 1.
Estou bem com isso, independentemente de ter alcançado este ponto por padrão. Eu sei que algumas pessoas sempre gostam de retornar a versão mais recente se um número não for especificado, mas IMHO que quebra todo o contrato & # x201C; estável & # x201D; objetivo; O que você obtém da API hoje pode ser completamente diferente do que você obtém amanhã se eu a revisar. Isso sugaria e isso quebraria coisas.
Você tem 3 opções, mas minha preferência pessoal é & # x2026;
Tenho o luxo de controlar a API e o principal consumidor de ser o próprio site da HIBP. Dado que eu forneci 3 opções para consumir a API, qual eu uso eu?
Eu fui com o favorito filosófico que é especificá-lo através do cabeçalho de aceitação. Eu não acho que isso é correto e os outros estão errados, e acho que isso faz mais sentido por duas razões principais:
Eu concordo que o URL não deve ser alterado: se concordarmos que o URL representa o recurso, a menos que tenhamos tentado representar diferentes versões do próprio recurso, então não, eu não acho que o URL deve mudar. As brechas para foo são sempre as brechas para foo e eu não acho que apenas porque eu mudo os dados retornados para que a localização do foo mude. Eu concordo que aceitar cabeçalho descreva como você gosta dos dados: Esta é uma semântica da especificação HTTP e assim como a semântica dos verbos de solicitação faz muito sentido (ou seja, estamos recebendo ou colocando ou excluindo ou postando) Da mesma forma, a maneira como o cliente gostaria que o conteúdo fosse representado.
De modo algum isso significa que eu acho que os outros dois estão errados e, francamente, não há melhor maneira de compartilhar a API com alguém do que dizer & # x201C; Aqui, clique neste & # x201D ;, mas quando eu puder construa facilmente a solicitação e gerencie os cabeçalhos, I & # x2019; fui com esta rota.
Na verdade, penso nisso, também uso a versão na rota do domínio. Por quê? Apenas através do processo de escrever esta API, eu estava constantemente me comunicando com as pessoas sobre as formas de consultá-lo (mais sobre isso mais tarde) e os atributos que retorna. Ser capaz de enviar um e-mail e dizer & # x201C; Ei, aqui, o que eu penso e # x201D; e eles simplesmente clicam nela e obtêm resultados inestimáveis. Este é o ponto que os proponentes da abordagem de versão de URL têm razão: você simplesmente não pode fazer isso quando você depende dos cabeçalhos.
Ah, e no caso de você voltar a verificar-me, no momento da escrita, eu ainda não enviei o site para v2 da API. Agora que os dados de violação são retirados na API quando ocorre uma pesquisa, significa que tenho o luxo de não carregar todas as violações na fonte na carga inicial (isso nunca mais será sustentável à medida que o conjunto de dados se expandir). Este salvará um monte de tráfego de saída e acelerará as coisas para as pessoas em termos de obter o site carregado, mas também significa apenas um pouco mais de trabalho no meu fim. Fique ligado.
No encerramento.
Claramente, eu fiquei um pouco embaixo da boca em relação a tudo o que está errado, mas, honestamente, quanto mais você lê sobre isso e quanto mais perguntas você faz, mais errado toda rota parece de uma forma ou de outra. Na verdade, eu sei muito bem que existem aspectos da minha implementação que serão referidos como & # x201C; wrong & # x201D; (Eu posso pensar em pelo menos um casal) e, naturalmente, estou me preparando para o ataque potencial de feedback para esse efeito. Entretanto, cada uma dessas opções funciona e, francamente, para todos os propósitos práticos, elas funcionam tão bem quanto entre si.
Se eu puder deixar outros considerando como versão suas APIs com um pensamento final: Ninguém usará sua API até que você a tenha construído. Pare de procrastinar. Nenhum destes são & # x201C; bad & # x201D; em qualquer sentido tangível, eles simplesmente são diferentes. Todos são facilmente consumíveis, todos retornam o mesmo resultado e nenhum deles provavelmente terá algum impacto real no sucesso do seu projeto.
Referências.
Sobrecarga de pilha: melhores práticas para o controle de versão da API? (ótima pergunta, ótimas respostas, fechadas como & # x201C; não construtivas & # x201D ;, eu assumi porque & # x201C; Bill the Lizard & # x201D; saiu no lado errado da cama naquela manhã) Lexical Scope blog: Como é REST APIs versão? (boa comparação de práticas de versão em todos os serviços), embora agora tenha dois anos de idade) CodePlex: exemplo de restrição de roteamento (vinculado na página da API da Web da Microsoft como um exemplo de APIs de versão adicionando um cabeçalho personalizado) CodeBetter: Versioning RESTful Serviços (muito pragmático e uma boa descrição das várias formas em que uma API pode mudar) O blog de Vinay Sahni & # x2019; Melhores Práticas para Projetar uma API RESTURA pragmática (ele está discutindo a versão de URL por causa de & # x201C Exploração do navegador & # x201D;) Pivotal Lans: versão de API (boa visão das opiniões conflitantes lá fora) Web Stack of Love: Versão da API Web ASP com tipos de mídia (bom passo a passo para a criação de um aplicativo para suportar o controle de versão por negociação de conteúdo)
Oi, Troy Hunt, escrevo este blog, crie cursos para a Pluralsight e sou Diretor Regional da Microsoft e MVP que viaja no mundo falando em eventos e treinando profissionais da tecnologia.
Oi, Troy Hunt, escrevo este blog, crie cursos para a Pluralsight e sou Diretor Regional da Microsoft e MVP que viaja no mundo falando em eventos e treinando profissionais da tecnologia.
Próximos eventos.
Costumo executar workshops particulares em torno destes, aqui estão os próximos eventos públicos em que irei:
Já não tem o Pluralsight? Que tal uma versão gratuita de 10 dias? Isso lhe dará acesso a milhares de cursos entre os quais são dezenas de meus, incluindo:
"The Cloud Never Goes Down", Azure SLAs e outras trivia de disponibilidade.
Veja como Bell foi pirateado - injeção SQL por sopro.
Inscreva-se agora!
Copyright 2018, Troy Hunt.
Este trabalho está licenciado sob uma licença internacional Creative Commons Attribution 4.0. Em outras palavras, compartilhe generosamente, mas forneça atribuição.
Aviso Legal.
As opiniões expressadas aqui são minhas e podem não refletir as pessoas com quem trabalho, meus companheiros, minha esposa, as crianças, etc. A menos que eu esteja citando alguém, eles são apenas meus próprios pontos de vista.
Publicado com o Ghost.
Este site funciona inteiramente no Ghost e é possível graças ao seu amável suporte. Leia mais sobre por que eu escolhi usar Ghost.

Quatro estratégias de versão da API REST.
Este artigo descreve quatro estratégias comuns de versão do REST API e explica como versão a API REST no xMatters.
Na xMatters, seguimos a especificação SemVer & # 8211; nós atualizamos a versão principal da API sempre que apresentamos mudanças de quebra. Internamente, atualizamos versões menores e patch sempre que adicionamos funcionalidades e atualizações compatíveis com versões anteriores. Quando lançamos uma nova versão principal da API REST do xMatters, os clientes podem optar por continuar usando uma versão principal existente ou migrar para a nova.
REST é, de longe, o estilo arquitetônico mais proeminente usado hoje para expor serviços a terceiros pela internet. Ele usa o padrão HTTP em vez de protocolos mais complexos, como SOAP ou RPC. A razão pela qual o REST foi tão bem sucedido é que imita como a web funciona:
Apátrida: não retém o contexto do cliente entre solicitações Cacheable: depende de regras de cache HTTP Orientação para cliente / servidor: separa preocupações entre clientes e servidores em camadas: aproveita um sistema em camadas e uma interface unificada.
Quatro estratégias comuns de controle de versão REST API.
Existem quatro maneiras comuns de versão de uma API REST.
1. Versões através do caminho URI.
Um caminho para a versão de uma API REST é incluir o número da versão no caminho do URL.
Esta estratégia é utilizada pela xMatters, bem como por outras empresas como Facebook, Twitter, Airbnb e outros.
Esta solução geralmente usa o roteamento URI para apontar para uma versão específica da API. Como as chaves de cache (nesta situação URIs) são alteradas pela versão, os clientes podem facilmente armazenar em cache os recursos. Quando uma nova versão da API REST é lançada, ela é percebida como uma nova entrada no cache.
A versão interna da API é a seguinte:
Versão principal: a versão usada na URI e denota alterações de quebra para a API. Internamente, uma nova versão importante implica criar uma nova API e o número da versão é usado para rotear para o host correto.
Versões menores e remessas: são transparentes para o cliente e são usadas internamente para atualizações compatíveis com versões anteriores. Eles geralmente são comunicados em logs de mudanças para informar os clientes sobre uma nova funcionalidade ou uma correção de bugs.
Esta solução tem uma pegada muito grande na base de código, pois introduzir mudanças de interrupção implica ramificar toda a API.
2. Versão através dos parâmetros da consulta.
Outra opção para a versão de uma API REST é incluir o número da versão como um parâmetro de consulta.
Esta é uma maneira direta de versão de uma API a partir do ponto de vista da implementação. Também é fácil predefinir a versão mais recente se um parâmetro de consulta não for especificado.
A principal desvantagem comparada à versão de URI é a dificuldade de roteamento. Os parâmetros de consulta são, de fato, mais difíceis de usar para rotear solicitações para a versão adequada da API.
3. Versões através de cabeçalhos personalizados.
As APIs REST também podem ser controladas através do fornecimento de cabeçalhos personalizados com o número de versão incluído como um atributo.
A principal diferença entre essa abordagem e as duas anteriores é que ela não destrói o URI com informações de versão.
4. Versões através da negociação de conteúdo.
Curl - H & # 8220; Aceitar: application / vnd. xm. device + json; versão = 1 e # 8221; exemplo / api / produtos.
A última estratégia que estamos abordando é o controle de versão através da negociação de conteúdo.
Esta abordagem nos permite a versão de uma única representação de recursos em vez de controlar a versão completa da API, o que nos dá um controle mais detalhado sobre o controle de versão. Ele também cria uma pegada menor na base de código, pois não precisamos empilhar todo o aplicativo ao criar uma nova versão. Outra vantagem desta abordagem é que não requer a implementação de regras de roteamento URI introduzidas pelo controle de versão através do caminho URI.
Uma das desvantagens desta abordagem é que é menos acessível do que as APIs com versão URI: exigir cabeçalhos HTTP com tipos de mídia torna mais difícil testar e explorar a API usando um navegador.
A negociação de conteúdo é uma abordagem mais granular porque ele representa as representações de recursos em vez de controlar a versão completa da API, mas também vem com um alto custo de implementação para clientes e desenvolvedores. Na maioria das vezes, a negociação de conteúdo precisa ser implementada a partir do zero, pois existem poucas bibliotecas que oferecem isso fora da caixa. As outras abordagens são mais fáceis de implementar e usar, mas limitam a capacidade do desenvolvedor de refatorar devido ao alto custo de introduzir mudanças de quebra no contrato da API.
Algum pensamento ou recomendação? Deixe um comentário abaixo!
Livro Branco gratuito: Saiba sobre o padrão + caso.
Saiba mais sobre como adotar uma abordagem holística para TI da Rob England em seu blog, The IT Skeptic, e de seus livros, incluindo Plus! A abordagem padrão + caso. Para obter mais informações, leia o novo white paper da Rob ao transformar situações de gerenciamento de casos indefinidas em novos modelos de resposta padrão, escritos para xMatters: padrão + caso: como os modelos de resposta de TI impulsionam as operações modernas.
Precisamos fazer o pacote (pasta) conforme a versão principal?
Outra questão é: como a versão do esquema, se a Mudança do Api requer mudança nas tabelas do banco de dados. algum link?
Uma coisa que não é muitas vezes documentada é como gerenciar o código e todas as versões suportadas pela API.
Estou interessado em encontrar um bom padrão para administrar nosso código e evitar o pesadelo da versão.
Minha implementação da 3ª abordagem para a primavera-webmvc:
Você também pode estar interessado em.
Como Hacked a experiência do Airbnb com a AT & # 038; T, HP e Intel.
A nova integração do ServiceNow reduz o tempo para resolver.
Moogsoft e integração de xMatters leva a gestão de incidentes para um novo nível.
Os trabalhos de Zombie não podem ser interrompidos por transmissões de e-mail.
Precisa de suporte?
Nosso site comunitário dedicado é o melhor lugar para obter ajuda em todos os produtos xMatters. Nossa equipe de pessoal de suporte especializado e usuários dentro de nossa comunidade podem ajudá-lo a obter a resposta correta.

As APIAS REST não precisam de uma estratégia de versão e # 8211; eles precisam de uma estratégia de mudança.
A mudança de uma API é inevitável à medida que seu conhecimento e experiência de um sistema melhoram. Gerenciando o impacto dessa mudança pode ser um grande desafio quando ameaça quebrar as integrações de clientes existentes.
Os desenvolvedores muitas vezes tentam decidir sobre uma estratégia de controle de versão assim que eles começam a trabalhar em uma API. Isso é compreensível, mas nem sempre é a maneira mais inteligente de olhar para o problema de gerenciar a mudança. Brandon Byers resumiu isso emprestando Jamie Zawinski & # 8217; s cavar em expressões regulares:
Algumas pessoas, quando confrontadas com um problema, pensam que eu conheço, eu uso o controle de versão. # 8221; Agora eles têm 2.1.0 problemas.
Como você pode recursos de versão em REST?
O REST não fornece nenhum controle de versão específico, mas as abordagens mais comumente usadas se dividem em três campos: colocando-o no URI, usando um cabeçalho de solicitação personalizado ou adicionando-o ao cabeçalho HTTP Accept.
Usando o URI é a abordagem mais direta, embora ele tenha perturbado os defensores de REST que insistem em que um URI deve se referir a um recurso exclusivo. Você também está garantido para interromper as integrações do cliente quando uma versão é atualizada, independentemente de você investir em roteamento criativo e comunicação com o cliente.
Um cabeçalho personalizado permite que você preserve seus URIs entre as versões, embora seja efetivamente uma duplicação do comportamento de negociação de conteúdo implementado pelo cabeçalho Accept existente. Um cliente pode usar esse cabeçalho para enviar uma lista de versões suportadas enquanto o servidor responde com a versão usada no cabeçalho Content-Type.
A negociação do conteúdo pode permitir que você preserve um conjunto limpo de URLs, mas você ainda precisa lidar com a complexidade de servir diferentes versões de conteúdo em algum lugar. Este fardo tende a ser movido para cima da pilha para seus controladores de API, que se tornam responsáveis ​​por descobrir qual versão de um recurso enviar. O resultado final tende a ser uma API mais complexa, pois os clientes devem saber quais cabeçalhos especificar antes de solicitar um recurso.
O número da versão não é o problema.
Dada a natureza contenciosa do REST, você sempre estará errado nos olhos de alguém, não importa qual abordagem você toma. O ponto é que a numeração da versão em si é um arenque vermelho.
O verdadeiro desafio aqui é o gerenciamento de uma base de código que pode oferecer várias versões de recursos. Se você mantiver todas as versões na mesma base de código, as versões mais antigas tornam-se vulneráveis ​​a mudanças inesperadas. Se você separar as bases do código, as despesas gerais operacionais e de suporte aumentam. Em ambos os casos, o bloqueio de código e a crescente complexidade são uma consequência inevitável.
Uma abordagem rigorosa para o controle de versão oferece uma certeza muito necessária sobre o contrato, mas tende a prejudicar a capacidade de mudança de um sistema. A versão pode tornar-se uma barreira para a melhoria, uma vez que todos os requisitos que levam a alterações de versão são resistidos. Eu vi APIs com políticas de controle de versão rígidas presas na mesma versão por anos devido a preocupações legítimas sobre a quantidade de trabalho e os riscos envolvidos na mudança.
Qual a alternativa ao controle de versão?
Uma estratégia de versão coerente deve abordar como você gerenciará a mudança em sua API, ao mesmo tempo que proporcionará um contrato estável para os clientes. Isso não precisa incluir a emissão de novas versões em resposta a mudanças.
Uma abordagem é construir a possibilidade de mudança, fornecendo compatibilidade com versões anteriores nas mudanças da API. Esta abordagem traz riscos significativos, pois não pode ter certeza de que uma mudança não quebre clientes existentes mesmo com testes de regressão exaustivos.
Você pode mesmo levar a compatibilidade para trás um passo adiante, adicionando recursos como parâmetros opcionais e propriedades curinga que antecipam futuras mudanças. Este tipo de "compatibilidade de avarias" tende a produzir um contrato grosseiro que coloca um fardo considerável de validação no cliente. O resultado final é muitas vezes um conjunto desordenado de switches e códigos necessários para cada chamada.
O princípio Open \ Closed de Bertrand Meyer sugere que as entidades de software devem ser "abertas para extensão, mas fechadas para modificação". Quando aplicado às APIs, a implicação é que você pode aumentar seus recursos, mas não alterá-los.
Esta abordagem poderia oferecer a certeza de versões mais estritas sem os riscos de regressão envolvidos na compatibilidade com versões anteriores. O aumento não está sem seus problemas, pois pode dar origem a contratos inchados. Sem disciplina cuidadosa, uma API pode ficar cheia de métodos ou recursos duplicados que fornecem várias maneiras ligeiramente diferentes de alcançar a mesma coisa.
Você pode compartilhar a responsabilidade?
Você poderia fazer mais para compartilhar o peso da mudança entre API e cliente. A lei de Postel, muitas vezes referida como o princípio da robustez, afirma que você deveria ser "liberal no que você aceita e conservador no que você envia". Em termos de API, isto implica uma certa tolerância nos serviços de consumo.
Por exemplo, técnicas rigorosas de serialização podem ser desnecessariamente intolerantes à mudança. Um leitor mais tolerante só deve se preocupar com os dados que ele precisa e ignorar todas as outras partes da resposta. Isso significa que a maioria das mudanças não é susceptível de quebrar a integração.
Outra abordagem poderia ser para o consumidor declarar os dados que eles estão interessados ​​como parte de um pedido. Esse padrão de contrato orientado pelo consumidor não especifica a forma que essas afirmações de consumidores devem levar, mas uma implementação pode permitir que uma API detecte quando uma solicitação está desatualizada.
Infelizmente, essas abordagens só podem ser aplicadas a comunidades de serviços relativamente fechadas. As APIs voltadas para o público raramente têm o luxo de poder ditar o estilo de integração do cliente. O único contrato executável que você possui entre o serviço e o cliente é composto pelos dados e pelo protocolo.
É por isso que uma disciplina cuidadosa é o cerne de qualquer estratégia de mudança sensível. Uma boa API não ocorre por acidente. Tem que ser curado. Seja qual for a abordagem que você toma para gerenciar a mudança, você precisará de uma governança consistente e ativa sobre o contrato em constante evolução.
Eu sou um arquiteto técnico com sede em Londres que passou mais de vinte anos no desenvolvimento de liderança em empreendimentos iniciais, agências digitais, casas de software e corporações. Ao longo dos anos, criei muitas coisas, incluindo sites e serviços, aplicativos multi-tela, integrações de sistemas e middleware.
Meu foco atual é permitir a entrega SaaS escalável e fornecer liderança arquitetônica em ambientes ágeis. Atualmente trabalho para o provedor SaaS Fourth levando-os ao céu empresarial, um serviço por vez.
Você pode me seguir no Twitter ou me visitar no LinkedIn.
Serviços de entidades: quando os microservices são piores do que os monólitos.
Os serviços finamente criados e baseados em entidades parecem ser defendidos por algumas fontes bastante autorizadas. Isso é infeliz porque eles são algo de um anti-padrão que pode prejudicar muitos dos benefícios de decompor um monólito em micoservices.
Esqueça a cobertura do código - o design do teste deve ser conduzido por comportamentos.
As estatísticas de cobertura de teste são muito apreciadas pelas equipes de gerenciamento e ferramentas de qualidade de código. Eles tendem a associar um alto nível de cobertura com bases de código robustas e bem gerenciadas. Errado, como se mostra.
Eventos, sagas e fluxos de trabalho: gerenciamento de processos de longo prazo entre serviços.
Uma arquitetura baseada em eventos pode dar origem a complexas cadeias de eventos que são difíceis de gerenciar. Esses problemas podem ser atenuados através de um design cuidadoso em vez de recorrer a bancos de dados de estado compartilhados ou a mecanismos de fluxo de trabalho.
A dívida técnica é uma metáfora excessivamente usada e preguiçosa.
A dívida técnica pode ser uma metáfora útil para descrever como o design incorreto do código prejudica a produtividade para públicos não técnicos, mas não ajuda na compreensão dos problemas a longo prazo que afetam as bases de código.
Como o Domain Driven Design pode ajudar com o desenvolvimento ágil em grande escala?
As equipes ágeis passam o software de modelagem do tempo se estão dispostas a admitir ou não. A adoção de uma técnica como o Domain Driven Design pode ajudar a tornar isso mais eficiente, particularmente em escala.
Executando um aplicativo de console do núcleo como um serviço do Windows.
Embora o Core não suporte diretamente a criação de serviços do Windows, existem várias formas diferentes de criar aplicativos que podem ser registrados e executados como serviços.
Quando a refatoração se torna reescrita?
Refatoração descreve uma técnica muito específica e controlada para melhorar o código. The problem is that it is often used to describe wholesale changes to code bases that should be treated as a rewrite.
Writing unit tests for Azure Functions using C#
You can now write compiled Azure functions in C# with full unit test coverage, though there are a few obstacles along the way.

Rest api versioning strategy


Obter através da App Store Leia esta publicação em nosso aplicativo!
Best practices for API versioning? [fechadas]
Are there any known how-tos or best practices for web service REST API versioning?
I have noticed that AWS does versioning by the URL of the endpoint. Is this the only way or are there other ways to accomplish the same goal? If there are multiple ways, what are the merits of each way?
closed as primarily opinion-based by templatetypedef, amon, George Stocker ♦ Mar 6 '14 at 13:22.
Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise. Se esta questão pode ser reformulada para ajustar as regras no centro de ajuda, edite a questão.
locked by animuson ♦ Mar 8 '16 at 3:40.
Esta questão existe porque tem significado histórico, mas não é considerada uma boa questão no tópico para este site, portanto, não use isso como evidência de que você pode fazer perguntas semelhantes aqui. Esta pergunta e suas respostas estão congeladas e não podem ser alteradas. Mais informações: centro de ajuda.
This is a good and a tricky question. The topic of URI design is at the same time the most prominent part of a REST API and , therefore, a potentially long-term commitment towards the users of that API .
Since evolution of an application and, to a lesser extent, its API is a fact of life and that it's even similar to the evolution of a seemingly complex product like a programming language, the URI design should have less natural constraints and it should be preserved over time . The longer the application's and API's lifespan, the greater the commitment to the users of the application and API.
On the other hand, another fact of life is that it is hard to foresee all the resources and their aspects that would be consumed through the API. Luckily, it is not necessary to design the entire API which will be used until Apocalypse. It is sufficient to correctly define all the resource end-points and the addressing scheme of every resource and resource instance.
Over time you may need to add new resources and new attributes to each particular resource, but the method that API users follow to access a particular resources should not change once a resource addressing scheme becomes public and therefore final.
This method applies to HTTP verb semantics (e. g. PUT should always update/replace) and HTTP status codes that are supported in earlier API versions (they should continue to work so that API clients that have worked without human intervention should be able to continue to work like that).
Furthermore, since embedding of API version into the URI would disrupt the concept of hypermedia as the engine of application state (stated in Roy T. Fieldings PhD dissertation) by having a resource address/URI that would change over time, I would conclude that API versions should not be kept in resource URIs for a long time meaning that resource URIs that API users can depend on should be permalinks .
Sure, it is possible to embed API version in base URI but only for reasonable and restricted uses like debugging a API client that works with the the new API version. Such versioned APIs should be time-limited and available to limited groups of API users (like during closed betas) only. Otherwise, you commit yourself where you shouldn't.
A couple of thoughts regarding maintenance of API versions that have expiration date on them. All programming platforms/languages commonly used to implement web services (Java, , PHP, Perl, Rails, etc.) allow easy binding of web service end-point(s) to a base URI. This way it's easy to gather and keep a collection of files/classes/methods separate across different API versions .
From the API users POV, it's also easier to work with and bind to a particular API version when it's this obvious but only for limited time, i. e. during development.
From the API maintainer's POV, it's easier to maintain different API versions in parallel by using source control systems that predominantly work on files as the smallest unit of (source code) versioning.
However, with API versions clearly visible in URI there's a caveat: one might also object this approach since API history becomes visible/aparent in the URI design and therefore is prone to changes over time which goes against the guidelines of REST. Concordo!
The way to go around this reasonable objection, is to implement the latest API version under versionless API base URI. In this case, API client developers can choose to either:
develop against the latest one (committing themselves to maintain the application protecting it from eventual API changes that might break their badly designed API client ).
bind to a specific version of the API (which becomes apparent) but only for a limited time.
For example, if API v3.0 is the latest API version, the following two should be aliases (i. e. behave identically to all API requests):
In addition, API clients that still try to point to the old API should be informed to use the latest previous API version, if the API version they're using is obsolete or not supported anymore . So accessing any of the obsolete URIs like these:
should return any of the 30x HTTP status codes that indicate redirection that are used in conjunction with Location HTTP header that redirects to the appropriate version of resource URI which remain to be this one:
There are at least two redirection HTTP status codes that are appropriate for API versioning scenarios:
301 Moved permanently indicating that the resource with a requested URI is moved permanently to another URI (which should be a resource instance permalink that does not contain API version info). This status code can be used to indicate an obsolete/unsupported API version, informing API client that a versioned resource URI been replaced by a resource permalink .
302 Found indicating that the requested resource temporarily is located at another location, while requested URI may still supported. This status code may be useful when the version-less URIs are temporarily unavailable and that a request should be repeated using the redirection address (e. g. pointing to the URI with APi version embedded) and we want to tell clients to keep using it (i. e. the permalinks).
The URL should NOT contain the versions. The version has nothing to do with "idea" of the resource you are requesting. You should try to think of the URL as being a path to the concept you would like - not how you want the item returned. The version dictates the representation of the object, not the concept of the object. As other posters have said, you should be specifying the format (including version) in the request header.
If you look at the full HTTP request for the URLs which have versions, it looks like this:
The header contains the line which contains the representation you are asking for ("Accept: application/xml"). That is where the version should go. Everyone seems to gloss over the fact that you may want the same thing in different formats and that the client should be able ask for what it wants. In the above example, the client is asking for ANY XML representation of the resource - not really the true representation of what it wants. The server could, in theory, return something completely unrelated to the request as long as it was XML and it would have to be parsed to realize it is wrong.
A better way is:
Further, lets say the clients think the XML is too verbose and now they want JSON instead. In the other examples you would have to have a new URL for the same customer, so you would end up with:
(or something similar). When in fact, every HTTP requests contains the format you are looking for:
Using this method, you have much more freedom in design and are actually adhering to the original idea of REST. You can change versions without disrupting clients, or incrementally change clients as the APIs are changed. If you choose to stop supporting a representation, you can respond to the requests with HTTP status code or custom codes. The client can also verify the response is in the correct format, and validate the XML.
One last example to show how putting the version in the URL is bad. Lets say you want some piece of information inside the object, and you have versioned your various objects (customers are v3.0, orders are v2.0, and shipto object is v4.2). Here is the nasty URL you must supply in the client:
We found it practical and useful to put the version in the URL. It makes it easy to tell what you're using at a glance. We do alias /foo to /foo/(latest versions) for ease of use, shorter / cleaner URLs, etc, as the accepted answer suggests.
Keeping backwards compatibility forever is often cost-prohibitive and/or very difficult. We prefer to give advanced notice of deprecation, redirects like suggested here, docs, and other mechanisms.
I agree that versioning the resource representation better follows the REST approach. but, one big problem with custom MIME types (or MIME types that append a version parameter) is the poor support to write to Accept and Content-Type headers in HTML and JavaScript.
For example, it is not possible IMO to POST with the following headers in HTML5 forms, in order to create a resource:
This is because the HTML5 enctype attribute is an enumeration, therefore anything other than the usual application/x-www-formurlencoded , multipart/form-data and text/plain are invalid.
. nor am I sure it is supported across all browsers in HTML4 (which has a more lax encytpe attribute, but would be a browser implementation issue as to whether the MIME type was forwarded)
Because of this I now feel the most appropriate way to version is via the URI, but I accept that it is not the 'correct' way.
Put your version in the URI. One version of an API will not always support the types from another, so the argument that resources are merely migrated from one version to another is just plain wrong. It's not the same as switching format from XML to JSON. The types may not exist, or they may have changed semantically.
Versions are part of the resource address. You're routing from one API to another. It's not RESTful to hide addressing in the header.
There are a few places you can do versioning in a REST API:
As noted, in the URI. This can be tractable and even esthetically pleasing if redirects and the like are used well.
In the Accepts: header, so the version is in the filetype. Like 'mp3' vs 'mp4'. This will also work, though IMO it works a bit less nicely than.
In the resource itself. Many file formats have their version numbers embedded in them, typically in the header; this allows newer software to 'just work' by understanding all existing versions of the filetype while older software can punt if an unsupported (newer) version is specified. In the context of a REST API, it means that your URIs never have to change, just your response to the particular version of data you were handed.
I can see reasons to use all three approaches:
if you like doing 'clean sweep' new APIs, or for major version changes where you want such an approach. if you want the client to know before it does a PUT/POST whether it's going to work or not. if it's okay if the client has to do its PUT/POST to find out if it's going to work.
Versioning your REST API is analogous to the versioning of any other API. Minor changes can be done in place, major changes might require a whole new API. The easiest for you is to start from scratch every time, which is when putting the version in the URL makes most sense. If you want to make life easier for the client you try to maintain backwards compatibility, which you can do with deprecation (permanent redirect), resources in several versions etc. This is more fiddly and requires more effort. But it's also what REST encourages in "Cool URIs don't change".
In the end it's just like any other API design. Weigh effort against client convenience. Consider adopting semantic versioning for your API, which makes it clear for your clients how backwards compatible your new version is.

Versioning a REST API.
Last modified: July 20, 2017.
I just announced the new Spring 5 modules in REST With Spring:
1. The Problem.
Evolving a REST API is a difficult problem – one for which many options are available. This article discusses through some of these options.
2. What is in the Contract?
Before anything else, we need to answer one simple question: What is the Contract between the API and the Client?
2.1. URIs part of the Contract?
Let’s first consider the URI structure of the REST API – is that part of the contract? Should clients bookmark, hardcode and generally rely on URIs of the API?
If they would, then the interaction of the Client with the REST Service would no longer be driven by the Service itself, but by what Roy Fielding calls out-of-band information :
A REST API should be entered with no prior knowledge beyond the initial URI (bookmark) and set of standardized media types that are appropriate for the intended audience…Failure here implies that out-of-band information is driving interaction instead of hypertext.
So clearly URIs are not part of the contract ! The client should only know a single URI – the entry point to the API – all other URIs should be discovered while consuming the API.
2.2. Media Types part of the Contract?
What about the Media Type information used for the representations of Resources – are these part of the contract between the Client and the Service?
In order to successfully consume the API, the Client must have prior knowledge of these Media Types – in fact, the definition of these media types represents the entire contract, and is where the REST Service should focus the most:
A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types.
So the Media Type definitions are part of the contract and should be prior knowledge for the client that consumes the API – this is where standardization comes in.
We now have a good idea of what the contract is, let’s move on to how to actually tackle the versioning problem.
3. High Level Options.
Let’s now discuss the high level approaches to versioning the REST API:
URI Versioning – version the URI space using version indicators Media Type Versioning – version the Representation of the Resource.
When we introduce the version in the URI space , the Representations of Resources are considered immutable, so when changes need to be introduced in the API, a new URI space needs to be created.
For example , say an API publishes the following resources – users and privileges:
Now, let’s consider that a breaking change in the users API requires a second version to be introduced :
When we version the Media Type and extend the language , we go through Content Negotiation based on this header. The REST API would make use of custom vendor MIME media types instead of generic media types such as application/json . It is these media types that are going to be versioned instead of the URIs.
What is important to understand here is that the client makes no assumptions about the structure of the response beyond what is defined in the media type. This is why generic media types are not ideal – these do not provide enough semantic information and force the client to use require additional hints to process the actual representation of the resource.
An exception to this is using some other way of uniquely identifying the semantics of the content – such as an XML schema.
4. Advantages and Disadvantages.
Now that we have a clear concept of what is part of the Contract between the Client and the Service, as well as a high level overview of the options to version the API, let’s discuss the advantages and disadvantages of each approach.
First, introducing version identifiers in the URI leads to a very large URI footprint . This is due to the fact that any breaking change in any of the published APIs will introduce a whole new tree of representations for the entire API. Over time, this becomes a burden to maintain as well as a problem for the client – which now has more options to choose from.
Version identifiers in the URI is also severely inflexible – there is no way to simply evolve the API of a single Resource, or a small subset of the overall API. As we mentioned before, this is an all or nothing approach – if part of the API moves to the new version, then the entire API has to move along with it. This also makes upgrading clients from v1 to v2 a major undertaking – which leads to slower upgrades and much longer sunset periods for the old versions.
HTTP Caching is also a major concern when it comes to versioning.
From the perspective of proxy caches in the middle , each approach has advantages and disadvantages: if the URI is versioned, then the cache will need to keep multiple copies of each Resource – one for every version of the API. This puts load on the cache and decreases the cache hit rate, since different clients will use different versions. Also, some cache invalidation mechanisms will no longer work. If the media type is the one that is versioned, then both the Client and the Service need to support the Vary HTTP header to indicate that there are multiple versions being cached.
From the perspective of client caching however, the solution that versions the media type involves slightly more work than the one where URIs contain the version identifier. This is because it’s simply easier to cache something when its key is an URL than a media type.
Let’s end this section with defining some goals (straight out of API Evolution):
keep compatible changes out of names avoid new major versions makes changes backwards-compatible think about forwards-compatibility.
5. Possible Changes to the API.
Next, let’s consider the types of changes to the REST API – these are introduced here:
representation format changes resource changes.
5.1. Adding to the Representation of a Resource.
The format documentation of the media type should be designed with forward compatibility in mind; specifically – a client should ignore information that it doesn’t understand (which JSON does better than XML).
Now, adding information in the Representation of a resource will not break existing clients if these are correctly implemented.
To continue our earlier example , adding the amount in the representation of the user will not be a breaking change:
5.2. Removing or changing an existing Representation.
Removing, renaming or generally restructuring information in the design of existing representations is a breaking change for clients, because they already understand and rely on the old format.
This is where Content Negotiation comes in – for such changes, a new vendor MIME media type needs to be introduced.
Let’s continue with the previous example – say we want to break the name of the user into firstname and lastname :
As such, this does represent an incompatible change for the Client – which will have to request the new Representation and understand the new semantics, but the URI space will remain stable and will not be affected.
5.3. Major Semantic Changes.
These are changes in the meaning of the Resources, the relations between them or what the map to in the backend. This kinds of changes may require a new media type, or they may require publishing a new, sibling Resource next to the old one and making use of linking to point to it.
While this sounds like using version identifiers in the URI all over again, the important distinction is that the new Resource is published independently of any other Resources in the API and will not fork the entire API at the root.
The REST API should adhere to the HATEOAS constraint – most of the URIs should be DISCOVERED by Clients, not hardcoded. Changing such an URI should not be considered an incompatible change – the new URI can replace the old one and Clients will be able to re-discover the URI and still function.
It is worth noting however that, while using version identifiers in the URI is problematic for all of these reasons, it is not un-RESTful in any way.
6. Conclusion.
This article tried to provide an overview of the very diverse and difficult problem of evolving a REST Service . We discussed the two common solutions, advantages and disadvantages of each one, and ways to reason about these approaches in the context of REST. The article concludes by making the case for the second solution – versioning the media types , while examining the possible changes to a RESTful API.
7. Further Reading.
Usually these reading resources are linked throughout the article, but in these case, there are simply to many good ones:
I just announced the new Spring 5 modules in REST With Spring:
Whats wrong about setting an additional header like “X-apiversion” ?
Seems legit to me.
There are many problems with using your own custom request header to do versioning – here’s just a few:
& # 8211; caching won’t work at all – which is huge red flag.
& # 8211; the resource is now identified by more than the URI.
Espero que ajude. Felicidades.
Artigo interessante. With the hateoas links in a response how should you indicate that a versioned media type should be sent n the request?
I suppose that if the client was smart enough to supply it they will do it for the next request.
The media types are the only part that the client needs to have prior knowledge of. Check out the part about media types above.

No comments:

Post a Comment