Saturday 10 March 2018

Estratégia de controle de versão do api


Formas de versão de sua API, Parte 2.
Esta é parte dois de uma série no controle de versão da API. A Parte Um abrangia os métodos prevalecentes para a versão de sua API e permitindo que os clientes codificassem em uma versão especificamente. Eu sugiro que você leia essa publicação (pelo menos descreva a introdução!) Antes disso, pois fornece algum contexto necessário. Nele, sugeri um outro método que utiliza alguns conceitos pouco conhecidos das especificações do cabeçalho de Aceitação, que pode permitir que você faça uma API sem versão. Eu admitirei bem na frente, no entanto, é um pouco equivocado, mas acho que é importante. Você ainda pode editar as coisas na API, mas você não pode controlar a própria interface. Você está simplesmente a controlar as representações de recursos.
A alteração mais comum em qualquer API REST arquitetada é adicionar, alterar ou remover campos dos recursos. Novas informações são adicionadas ou podem estar em um formato diferente. As informações podem ficar indisponíveis. Você também pode adicionar, mover ou remover recursos. Dependendo da sua arquitetura API, os verbos HTTP podem significar coisas ligeiramente diferentes. Todos esses normalmente exigiriam um incremento da versão da API se eles causassem que os aplicativos existentes se quebrassem. Com um pouco de previsão, no entanto, sua API pode mudar sem exigir uma estratégia de controle de API completa.
Arquiteto uma interface sem versão:
Use esquemas de URI sãos: / api / collection_name / resource_id Siga as definições de métodos HTTP A adição de recursos deve sempre ser compatível com versões anteriores A remoção de recursos deveria ser feita através de versões de qualquer maneira. Os recursos móveis podem ser gerenciados por redirecionar códigos HTTP.
Representações de recursos de versão:
Use o cabeçalho de Aceitação A adição de informações deve sempre ser compatível com versões anteriores. A remoção de informações teria que ser feita através de versões de qualquer maneira. As informações de mudança podem ser feitas com Aceitação de versão.
Arquitetando uma API sem versão.
Deixe-me começar por dizer que eu reconheço que uma API sem versão é um pouco de um estado ideal, e uma API com uma estratégia de controle de versões bem pensada é muito preferível a uma API com uma tentativa mal pensada de não versão. Não há vergonha em dizer que você acha que precisa do controle de versão, nem que todas as APIs possíveis se encaixam nessa estratégia sem versão. Isso realmente funciona apenas para as APIs baseadas em manipulação de recursos com REST, que se seguem aos padrões vigentes. Dito isto, uma grande quantidade de APIs pode ser retrabalhada para se encaixar nesse estilo. Além disso, isso é destinado a APIs back-end, e não interfaces de interface com seu front-end na web. Na minha opinião, estas devem ser quase sempre APIs separadas para que você possa atualizar a funcionalidade de front-end da Web em seu próprio ritmo sem se preocupar com nenhum usuário da API. Eu sei que eu pessoalmente sou muito mais relaxado no meu seguimento de padrões para APIs front-end.
O primeiro passo para entender como criar uma API sem versão é saber que você não deseja versão da própria interface. Isso significa que você não quer mudar como e onde as informações são armazenadas e acessadas. Em termos práticos, esta é a estrutura URI. Mesmo esta regra pode ser dobrada, é claro - construída diretamente na especificação HTTP são redirecionamentos! Se você moviu informações, simplesmente forneça um redirecionamento permanente para o novo URI. Agora, o que acontece se você remover um recurso?
Os dois motivos por que um URI particular pode ser removido de uma API típica: ou o próprio tipo de recurso foi removido, ou mais comumente, que a representação particular do recurso não é mais suportada. No último caso, você realmente não aderiu à arquitetura REST: a representação do recurso deve ser desacoplada do URI. No caso anterior, se o tipo de recurso inteiro já não estiver acessível, é provavelmente por uma razão comercial, caso em que você deseja removê-lo de todas as versões anteriores da API também. Nesse caso, o controle de versão não conseguiu realmente nada, não é?
Adicionar recursos, ou informações aos recursos, sempre deve ser uma mudança compatível com versões anteriores. Se você estiver usando o JSON, adicionar elementos aos recursos existentes deve ser uma brisa. Mesmo que você tenha um esquema XML, você pode simplesmente adicioná-los ao esquema definido e alertar os clientes que podem ter baixado sua própria cópia do esquema para atualizá-lo. Se você quiser adicionar um recurso totalmente novo, basta adicioná-lo! Ninguém deve ser afetado.
Provavelmente, a coisa mais difícil de fazer versões sem alterações é o que acontece quando você executa um método específico em uma determinada API. Por exemplo, se você pudesse POST para / api / foo / e crie um novo recurso foo para você, mas agora você deseja que ele edite um recurso foo existente. O melhor que posso dizer é que não, em vez disso, siga as definições recomendadas do método de especificação HTTP explicitamente:
GET / api / foo / ou GET / api / foo / 1 recupera recursos ou recursos e é idempotente (repetitivo com os mesmos resultados) POST / api / foo / cria novos recursos e NÃO é idempotente (a repetição cria mais recursos) PUT / api / foo / 1 atualiza ou cria um recurso específico inteiro e são campos de atualizações idempotentes PATCH / api / foo / 1 (padrão proposto) de um recurso específico e é idempotente DELETE / api / foo / 1 exclui um recurso (às vezes coleções de recursos) e é idempotente.
Tecnicamente, acho que o DELETE deve notificar de alguma forma se o recurso não existisse em primeiro lugar e uma maneira apropriada de fazer isso seria um erro, mas eu vou adiar nisso. OPTIONS e HEAD são usados ​​menos e se você estiver usando eles, você provavelmente sabe o que você está fazendo de qualquer maneira. Se você estiver usando PATCH, esteja ciente de que não é um padrão bem suportado, e muitas API aceitarão pedidos PUT incompletos e somente atualizarão os campos alterados. Eu acho que isso está bem, desde que seja um comportamento bem compreensivo e documentado, com suporte PATCH manchado, pelo menos até que seja mais aceitável.
Muitas vezes, os recursos são modificados pelos pedidos POST. Um formulário envia, você interpreta os dados e muda um recurso. Este é um padrão comum em APIs de front-end, e como eu mencionei acima, isso é bom. Não é perfeito, mas bom. Em uma API de back-end, isso não deve acontecer! Use uma solicitação PUT ou PATCH e defina explicitamente o que deseja que o novo recurso seja. Uma desculpa comum é as versões antigas do IE don & # 8217; t suporte PUT ou PATCH, mas esta é uma API de back-end, ela é boa! Todas as principais bibliotecas que conheço pelo menos suportam PUT - se você estiver usando um que não tenha, provavelmente você deve procurar em outro lugar.
Em suma, um pré-requisito para a inexatidão é que todos os recursos que você deve poder ser acessados ​​e manipulados em um fasion consistente, sendo as únicas diretivas o URI para o recurso, o método HTTP e os dados que representam o próprio recurso. Se você estiver manipulando um único recurso lógico - digamos, um perfil de usuário - de várias URIs, você provavelmente encontrará situações em que você precisa para a versão.
Versão de representações de recursos.
Como mencionei na introdução, as próprias representações de recursos transferidas para o cliente podem e provavelmente devem ser controladas. A beleza desta abordagem é que cada recurso pode ser versionado de forma independente. Se você mudar um recurso, um mês depois, você decide mudar um recurso diferente, você não precisará aumentar um contador de versão da API duas vezes. Cada versão do recurso é incrementada individualmente. Note-se que não estou falando sobre a versão dos próprios recursos, apenas a representação do recurso. Se você tiver um recurso versionado, por exemplo, um documento que tenha revisões anteriores disponíveis, estes devem ser acessados ​​separadamente do método I & # 8217; descrevendo aqui.
Familiarizar-se com a especificação de cabeçalho Accept provavelmente irá ajudá-lo a entender a verdadeira profundidade de quão longe as especificações podem ir para a prova de futuro. Quase todo mundo sabe que o cabeçalho Aceita especifica o tipo de MIME-Type que o solicitante espera, como application / json. Menos sabe que não pode apenas especificar um tipo, mas pode especificar vários tipos aceitáveis, bem como parâmetros em cada tipo. Para representar recursos de versão, nós iremos aproveitar os parâmetros de tipo.
I & # 8217; ll entrar e você considerou o seguinte:
Mesmo sem entender completamente o cabeçalho Aceites, você provavelmente pode adivinhar que essa seqüência de caracteres implica que ela espera que o aplicativo / vnd. example. foo digite o formato json, a versão 2, se disponível, e qualquer versão do contrário. Analisar o cabeçalho Aceitar de uma maneira consistente com as especificações pode ser difícil apenas porque muitas bibliotecas não analisam a caixa.
Então, quando você deve representar recursos de versão? Como mencionei acima, se você estiver removendo informações sobre um recurso, é provavelmente por uma razão comercial que você não quer mais exposto. Na era da transmissão comprimida de hoje, há pouco ganho para tirar da informação simplesmente porque você não sente mais útil. A adição de informações sempre deve ser possível de forma compatível com versões anteriores. Você pode querer versão em caso de alterar o nome e / ou o tipo de um campo, por exemplo, se você quiser (tempo de exemplo do mundo real!), Repurpose um campo booleano com o & # 8220; habilitado & # 8221; para um status mais genérico & # 8220; & # 8221; tipo de enum.
Agora, como faço isso?
Infelizmente, muito do que eu discuti aqui tem pouco ou nenhum suporte amplo na comunidade de pessoas que realmente criam API amplamente utilizadas. Eu suspeito que nenhuma parte pequena disso é devido à dificuldade em implementá-los em uma aplicação do mundo real. Dependendo da sua plataforma, pode ser fácil ou difícil, e poucas bibliotecas suportarão uma estratégia de controle como esta fora da caixa. O mais próximo que eu sei é o nó de resposição que suporta roteamento versionado com base em um cabeçalho de versão de aceitação.
Eu irei a passar por algumas bibliotecas e tentando estendê-las para suportar o controle de versão no futuro. Possivelmente tentando minha própria biblioteca que assa muito isso gratuitamente. Quanto mais fácil é para um desenvolvedor escrever código compatível com padrões, mais provável eles vão adotá-lo, porque, no final, se se resume à facilidade de desenvolvimento versus adesão aos padrões, acho que todos sabemos que a facilidade ganhará a cada vez .

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 & # x2013; 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 às pessoas & # x2013; & # x201C; Battlefield Heroes & # x201D; & # x2013; Mas, mais importante ainda, se Gawker for repetidamente, eu posso nomear a violação de algo como Gawker2014 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 & # x2013; forneça um nome de conta, receba uma lista de brechas & # x2013; 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 bateu a versão da API no URL, por exemplo: 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-version: 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 as razões práticas pelas quais isso faz sentido e isso é o que pode acontecer se você não fizer isso e # x201D ;, e eu sou 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 & # x2013; 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 e # x2013; não especifique uma versão & # x2013; 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.

estratégia de versão do Api
Obter através da App Store Leia esta publicação em nosso aplicativo!
Melhores práticas para o controle de versão da API? [fechadas]
Existem algumas práticas conhecidas ou práticas recomendadas para o controle de versão REST do serviço web?
Tenho notado que o AWS faz o controle de versão pela URL do ponto final. Este é o único caminho ou existem outras maneiras de atingir o mesmo objetivo? Se houver várias maneiras, quais são os méritos de cada caminho?
fechado como primeiramente baseado em opinião, por templatetypedef, amon, George Stocker & # 9830; 6 de março às 13h22.
Muitas boas perguntas geram algum grau de opinião com base na experiência de especialistas, mas as respostas a esta pergunta tendem a ser quase inteiramente baseadas em opiniões, ao invés de fatos, referências ou conhecimentos específicos. Se esta questão pode ser reformulada para ajustar as regras no centro de ajuda, edite a questão.
bloqueado por animuson & # 9830; 8 de março às 16h40.
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.
Esta é uma boa e complicada questão. O tópico de design URI é ao mesmo tempo a parte mais proeminente de uma API REST e, portanto, um compromisso potencialmente de longo prazo para com os usuários dessa API.
Uma vez que a evolução de uma aplicação e, em menor grau, a sua API é um fato da vida e que é mesmo semelhante à evolução de um produto aparentemente complexo como uma linguagem de programação, o design URI deve ter restrições menos naturais e deve ser preservado ao longo do tempo . Quanto maior o tempo de vida da aplicação e da API, maior o compromisso com os usuários do aplicativo e da API.
Por outro lado, outro fato da vida é que é difícil prever todos os recursos e seus aspectos que seriam consumidos através da API. Felizmente, não é necessário projetar toda a API que será usada até o Apocalypse. É suficiente definir corretamente todos os pontos finais do recurso e o esquema de endereçamento de cada recurso e instância de recursos.
Ao longo do tempo, talvez seja necessário adicionar novos recursos e novos atributos a cada recurso específico, mas o método que os usuários da API seguem para acessar um determinado recurso não deve mudar quando um esquema de endereçamento de recursos se torna público e, portanto, final.
Este método aplica-se a semântica de verbos HTTP (por exemplo, PUT deve sempre atualizar / substituir) e códigos de status HTTP que são suportados em versões anteriores da API (eles devem continuar funcionando para que os clientes da API que tenham trabalhado sem intervenção humana possam continuar a funcionar Curtiu isso).
Além disso, uma vez que a incorporação da versão da API no URI interromperia o conceito de hipermídia como o mecanismo do estado da aplicação (indicado na dissertação de doutorado de Roy T. Fieldings) por ter um endereço de recurso / URI que mudaria ao longo do tempo, eu concluiria que a API as versões não devem ser mantidas em URI de recursos por muito tempo, o que significa que os URIs de recursos em que os usuários da API podem depender devem ser permalinks.
Claro, é possível incorporar a versão da API no URI básico, mas apenas para usos razoáveis ​​e restritos, como depuração de um cliente da API que funciona com a nova versão da API. Essas APIs versionadas devem ser limitadas no tempo e estar disponíveis para grupos limitados de usuários de API (como no caso de betas fechadas). Caso contrário, você compromete-se onde você não deveria.
Um par de pensamentos sobre manutenção de versões API que tenham data de validade neles. Todas as plataformas de programação / idiomas comumente usados ​​para implementar serviços da Web (Java, PHP, Perl, Rails, etc.) permitem uma ligação fácil do (s) ponto (s) final do serviço web para um URI básico. Desta forma, é fácil reunir e manter uma coleção de arquivos / classes / métodos separados em diferentes versões da API.
A partir dos POVs da API, também é mais fácil trabalhar e ligar a uma determinada versão da API quando isso é óbvio, mas apenas por tempo limitado, ou seja, durante o desenvolvimento.
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.

Four REST API Versioning Strategies.
This article describes four common REST API versioning strategies and explains how we version the REST API at xMatters.
At xMatters, we follow the SemVer specification – we update the API major version whenever we introduce breaking changes. Internally, we update minor and patch versions whenever we add functionality and backward-compatible updates. When we release a new major version of the xMatters REST API, clients can choose to either continue using an existing major version or migrate to the new one.
REST is by far the most prominent architectural style used today to expose services to third parties over the internet. It uses the HTTP standard instead of more complex protocols like SOAP or RPC. The reason REST has been so successful is that it mimics how the web works:
Stateless: Doesn’t retain client context between requests Cacheable: Relies on HTTP caching rules Client/Server oriented: Separates concerns between clients and servers Layered: Leverages a layered system and a unified interface.
Four common REST API versioning strategies.
There are four common ways to version a REST API.
1. Versioning through URI Path.
One way to version a REST API is to include the version number in the URL path.
This strategy is used by xMatters as well as other companies such as Facebook, Twitter, Airbnb, and others.
This solution often uses URI routing to point to a specific version of the API. Because cache keys (in this situation URIs) are changed by version, clients can easily cache resources. When a new version of the REST API is released, it is perceived as a new entry in the cache.
The internal version of the API looks as follows:
Major version: The version used in the URI and denotes breaking changes to the API. Internally, a new major version implies creating a new API and the version number is used to route to the correct host.
Minor and Patch versions: These are transparent to the client and used internally for backward-compatible updates. They are usually communicated in change logs to inform clients about a new functionality or a bug fix.
This solution has a pretty big footprint in the code base as introducing breaking changes implies branching the entire API.
2. Versioning through query parameters.
Another option for versioning a REST API is to include the version number as a query parameter.
This is a straightforward way of versioning an API from an implementation point of view. It is also easy to default to the latest version if a query parameter is not specified.
The main drawback comparing to the URI versioning is the difficulty of routing. Query parameters are in fact more difficult to use for routing requests to the proper API version.
3. Versioning through custom headers.
REST APIs can also be versioned by providing custom headers with the version number included as an attribute.
The main difference between this approach and the two previous ones is that it doesn’t clutter the URI with versioning information.
4. Versioning through content negotiation.
curl - H “Accept: application/vnd. xm. device+json; version=1 ” example/api/products.
The last strategy we are addressing is versioning through content negotiation.
This approach allows us to version a single resource representation instead of versioning the entire API which gives us a more granular control over versioning. It also creates a smaller footprint in the code base as we don’t have to fork the entire application when creating a new version. Another advantage of this approach is that it doesn’t require implementing URI routing rules introduced by versioning through the URI path.
One of the drawbacks of this approach is that it is less accessible than URI-versioned APIs: Requiring HTTP headers with media types makes it more difficult to test and explore the API using a browser.
Content negotiation is a more granular approach because it versions resource representations instead of versioning the entire API, but it also comes with a high implementation cost for both clients and developers. More often than not, content negotiation needs to be implemented from scratch as there are few libraries that offer that out of the box. The other approaches are easier to implement and use but limit the developer’s ability to refactor due to the high cost of introducing breaking changes to the API contract.
Any thoughts or recommendations? Deixe um comentário abaixo!
Free White Paper: Learn About Standard+Case.
Learn more about taking a holistic approach to IT from Rob England at his blog, The IT Skeptic, and from his books, including Plus! The Standard+Case Approach. For more information, read Rob’s new white paper on turning undefined Case Management situations into new Standard Response Models, written for xMatters: Standard+Case: How IT Response Models Drive Modern Operations.
Do we need to make packging (folder) as per the major version ?
Another question is, How the version the schema if Api change require change in database tables. any link ?
One thing that is not very often documented is how to manage the code and all the versions that are supported by the API.
I’m interested to find a good pattern to manage our code and avoid version nightmare.
My implementation of 3rd approach for spring-webmvc:
Você também pode estar interessado em.
How We Hacked the Airbnb experience with AT&T, HP, and Intel.
New ServiceNow Integration Reduces Time to Resolve.
Moogsoft and xMatters Integration Takes Incident Management to a New Level.
Zombie Jobs Can’t Be Stopped By Email Broadcasts.
Need support?
Our dedicated community site is the best place to get help on all xMatters products. Our team of expert support staff and users inside our community can help you get the right answer.

REST APIs don’t need a versioning strategy – they need a change strategy.
Change in an API is inevitable as your knowledge and experience of a system improves. Managing the impact of this change can be quite a challenge when it threatens to break existing client integrations.
Developers often try to decide on a versioning strategy as soon as they start work on an API. This is understandable but it’s not always the smartest way of looking at the problem of managing change. Brandon Byers summed this up by borrowing Jamie Zawinski’s dig at regular expressions:
Some people, when confronted with a problem, think “I know, I’ll use versioning.” Now they have 2.1.0 problems.
How can you version resources in REST?
REST doesn’t provide for any specific versioning but the more commonly used approaches fall into three camps: putting it on the URI, using a custom request header or a adding it to the HTTP Accept header.
Using the URI is the most straightforward approach though it does upset REST advocates who insist that a URI should refer to a unique resource. You are also guaranteed to break client integrations when a version is updated no matter how heavily you invest in creative routing and client communication.
A custom header allows you to preserve your URIs between versions though it is effectively a duplicate of the content negotiation behaviour implemented by the existing Accept header. A client can use this header to send a list of supported versions while the server responds with the version used in the Content-Type header.
Content negotiation may let you to preserve a clean set of URLs but you still have to deal with the complexity of serving different versions of content somewhere . This burden tends to be moved up the stack to your API controllers which become responsible for figuring out which version of a resource to send. The end result tends to be a more complex API as clients have to know which headers to specify before requesting a resource.
The version number isn’t the problem.
Given the contentious nature of REST, you’ll always be wrong in somebody’s eyes no matter what approach you take. The point is that version numbering itself is a red herring.
The real challenge here is in managing a code base that can serve up multiple versions of resources. If you keep all versions in the same code base then older versions become vulnerable to unexpected changes. If you separate the code bases then the operational and support overhead escalates. In both cases, code bloat and increased complexity are an inevitable consequence.
A strict approach to versioning does give you much-needed certainty over the contract but it does tend to undermine a system’s capacity to change . Versioning can become a barrier to improvement as any requirements that lead to version changes are resisted. I have seen APIs with strict versioning policies stuck on the same version for years due to legitimate concerns over the amount of work and risk involved in change.
What’s the alternative to versioning?
A coherent version strategy should address how you will manage change in your API whilst providing a stable contract to clients. This doesn’t have to include issuing new versions in response to changes.
One approach is to build in the possibility of change by making provision for backwards compatibility in API changes. This approach does carry significant risk as you cannot be sure that a change will not break existing clients even with exhaustive regression testing.
You can even take backwards compatibility a step further by adding features such as optional parameters and wildcard properties that anticipate future changes. This kind of “ forwards compatibility ” tends to produce a coarse contract that places a considerable burden of validation onto the client. The end result is often a messy set of switches and codes required for each call.
Bertrand Meyer’s Open\Closed principle suggests that software entities should be “open for extension, but closed for modification”. When applied to APIs the implication is that you can augment your resources but not change them.
This approach could offer the certainty of stricter versioning without the regression risks involved in backwards compatibility. Augmentation is not without its problems though as it can give rise to bloated contracts. Without careful discipline an API can become littered with duplicate methods or resources that provide several slightly different ways of achieving the same thing.
Can you share the responsibility?
You could do more to share the burden of change between API and client. Postel’s law, often referred to as the Robustness principle, states that you should be “liberal in what you accept and conservative in what you send”. In terms of APIs this implies a certain tolerance in consuming services.
For example, strict serialization techniques can be unnecessarily intolerant of change. A more tolerant reader should only be concerned with data that it needs and ignore every other part of the response. This means that the majority of changes are unlikely to break the integration.
Another approach could be for the consumer to declare the data they are interested in as part of a request. This consumer-driven contract pattern does not specify the form that these consumer assertions should take, but an implementation could allow an API to detect when a request is out of date.
Unfortunately, these approaches can only be applied to relatively closed communities of services. Public-facing APIs rarely have the luxury of being able to dictate the style of client integration. The only enforceable contract you have between service and client is made up of the data and protocol.
This is why careful discipline is at the heart of any sensible change strategy. A good API doesn’t come into being by accident. It has to be curated . Whatever approach you take to managing change you will need consistent and active governance over the evolving contract.
I am a London-based technical architect who has spent more than twenty years leading development across start-ups, digital agencies, software houses and corporates. Over the years I have built a lot of stuff including web sites and services, multi-screen applications, systems integrations and middleware.
My current focus is on enabling scalable SaaS delivery and providing architectural leadership in agile environments. I currently work for SaaS provider Fourth leading them to enterprise heaven, one service at a time.
You can follow me on Twitter or check me out on LinkedIn.
Managing serverless scaling with Azure Functions by throttling throughput.
The serverless promise of unlimited scale-out can be a curse when your downstream processes and data stores have strict limits on throughput. With Azure Functions your options for mitigating this are limited, though the new durable functions may provide an answer…
Entity services: when microservices are worse than monoliths.
Finely-grained, entity-based services seem to be advocated by some pretty authoritative sources. This is unfortunate as they are something of an anti-pattern that can undermine many of the benefits of decomposing an monolith into micoservices.
Forget code coverage – test design should be driven by behaviours.
Test coverage statistics are much loved by management teams and code quality tools. They tend to associate a high level of coverage with robust, well-managed code bases. Wrongly, as it turns out.
Events, sagas and workflows: managing long-running processes between services.
An event-driven architecture can give rise to complex chains of events that are difficult to manage. These problems can be mitigated through careful design rather than resorting to shared state databases or workflow engines.
Technical debt is an overused and lazy metaphor.
Technical debt may be a useful metaphor for describing how bad code design undermines productivity to non-technical audiences, but it does not help in understanding the longer term problems that affect code bases.
How can Domain Driven Design help with large scale agile development?
Agile teams spend time modelling software whether they are prepared to admit it or not. Adopting a technique like Domain Driven Design can help to make this more efficient, particularly at scale.
Running a Core console application as a Windows Service.
Although Core does not directly support creating Windows Services there are several different ways of creating applications that can be registered and run as services.
When does refactoring become rewriting?
Refactoring describes a very specific and controlled technique for improving code. The problem is that it is often used to describe wholesale changes to code bases that should be treated as a rewrite.

Web API Versioning Strategy.
When you make any changes in the API, consumer should be able to continue using API in the way they were using before the changes were made. This is where the versioning is essential. This is a way in which the API evolves to add new features to it without breaking the current way of consuming it. In my view, this is not the same as new assembly version or new build. Whatever you change behind which the consumer cannot see in the API, should not require the new version of the API. The new version of the API should only be rolled out whenever “how to consume part changes”. Ex: when the resource or the signature changes.
If the API is a bit complex and serves for wide range consumers, then API versioning is a must. There exist different approaches. I will touch upon all of them with respect to ASP Web API versioning approaches and will suggest the best approach. I will also attempt to convince the reader with the appropriate examples and justification.
Approach #1: URI Versioning.
We will add the version number to the URI, then that URI maps to method on that controller.
Quite easy to implement. We can do it simply using the routing attribute over the method.
With the above approach we are breaking one of the constraints. The URI represents the resource and as long as the resource doesn’t change, the URI shouldn’t change as well. Of course, shouldn’t the URI to the same resource stay same? If the new version of the resource itself changes, then the new URI should be the valid approach. You might also want to make it accessible in a completely different URI. In that context, a new version of the resource is a different resource.
This approach is often used. One of the advantages with this is the browser exportability. We can access the different versions of the web API without having to resolve with applications like Fiddler to send custom requests to the web API. So we can categorize this one as a pragmatic approach.
Approach #2: Content Negotiation.
In the previous example, we get the message as JSON or XML by setting the content type as application/json or application/xml. Through Custom Content Type in the Accept Header, we can create custom content types which will tell the web API about which version to return in the accept header.
Here you are not only mentioning that you need data in JSON format but also information about the version. To create such API, vendor prefix “vnd” has to be used. It indicates that the content type is vendor specific and followed by a custom identifier, the version and the resource format.
In this approach, its a bit harder to browse the API in the browser. To invoke the API method, the request has to be built with the appropriate accept header.
Approach #3: Custom Request Header.
The third approach is the custom header added to request containing the version number. It’s a kind of Approach #2 but without the custom content type.
Here the API should read the custom header and from that info execute the correct version of the code.
It’s a bit harder to browse and the request has to be created with the custom request header.
The approaches described above can be used in combination as well. Like, major versions are requested through the URI and the minor versions are requested through the request header.
Approach #4: The URI Parameter Versioning.
This is an obvious one that I don’t see many people using:
This method is highly used by Amazon, Google and Netflix, but still it is not so popular. The client knows about what version he wants and the web API provider has no problem to maintain several versions. When no version is specified, the client will get the latest or default version. Newer versions will not break existing hyperlinks as we are using the URL parameter and will not change the resource name and location.
On the server-side, this feels a bit harder – the servers have to parse the entire parameter string before knowing where to route the request – something they try to avoid. Also, there is the same argument as not putting version numbers into the URI – the parameters are for specifying the services function not attributes of the implementation.
ASP Web API Implementation Examples:
Approach #1:
As simple as this, we just change the version in the routing attribute. So I would like to pay more attention to other two approaches Custom content Type and Custom Request Header .
Approach #2:
When a consumer requests a resource representation to a certain URI, we have to read out the custom content type request. We can able to read in API method using Request Headers and we execute the correct code depending on what we find in the header, but doing this inside the API method is not the best way because the request ends up in the same controller and method and then we have to process it.
This approach is better implemented through Custom Route Factory attributes and custom routing constraint. In the custom constraint, we will be able to check the accept header or the custom request header as we are going to implement both types of versioning. The Custom Route Factory attributes will then use that constraint and each constraint will have an opportunity to prevent the route from the given request.
We are going to create a custom route factory attribute, versioned route that adds a constraint to each attribute route and then potentially prevents the route. This will allow us to decorate the controller or a specific method in the controller with that attribute.
If the request matches our constraint logic, it then allows the correct route else prevents the route. To implement in a generic way I have a modified version of the custom class “Version Constraint”.
Web API method after the implementation of the about classes.
Example for Approach #2 custom content type in accept header:
Sample GET version 1 method for Versioning with Custom content type in header:
(version 1 invoke example is similar for Approach #2 and Approach #3)
Execution : request with API/report/1 URI version #1 will be invoked.
now requests with version #1 will match the above route. As we have mentioned version as #1 and its a default version, if we don’t pass the version in the header the default version #1 is executed.
Sample GET version 2 method for Versioning with Custom content type in accept header:
Execution: now to invoke version #2, in custom request header specify,
use same get call URI: API/report/1.
Accept: application/vnd. ServiceAPIname. v2+json (sepecify in accept header not in URI)
now it will invoke Version #2 get method.
Sample GET version 1 method for Versioning with Custom request header:
Execution : request with API/report/1 URI version #1 will be invoked.
now requests with version #1 will match the above route. As we have mentioned version as #1 and its a default version, if we don’t pass the version in the header the default version #1 is executed.
Sample GET version 2 method for Versioning with Custom request header:
Execution: now to invoke version #2, in custom request header specify,
use same get call URI: API/report/1.
API-version: 2 (specify in request header not in URI)
now it will invoke Version #2 method.
Facebook and Twitter are using a part of the URL that comes before the API Service definition and before the resource definition itself (for example example/v2.7/ ) because one may say that the whole URL is the resource identifier.
However some may say that the resource identifier is only the and what comes before that is the HOST and the API SERVICE identifier. It is a bit more clear when using twitter API: api. twitter/1.1/blocksabc, here the HOST = api. twitter, API Service = blocks and the API Service version which comes before the API Service definition 1.1.
Conclusão.
All versioning schemes are problematic if there is no necessity. Versioning is unnecessary if the clients are very few. For example, teams with just ONE client insist on a versioning scheme which is ridiculous. Resource type should not be changed in a way that its breaks backward compatibility. I have seen in many projects using “V1” in the resource URL such as “v1/GetData” and it never changes to “V2”. In such scenarios versioning is unnecessary.
I prefer Approach #3 – custom header for a strong reason. I will justify why I don’t like others. URL relationships are great for versioning when it involves changes to resources and behaviors (let’s say you move from “user” to “customer” which now does a back end billing and email process but doesn’t change the structure of the resource itself). But what about if you need to change something on a different layer, such as going from OAuth 1.0 to OAuth 2.0? Or you’re doing a pivot as a company? Or something else I haven’t even thought of yet? I don’t like the URL approaches because they simply do something about the resource representation where as a header is, again, on a much higher layer. I hope to never change our header versioning, but having it there as a required parameter ensures we’ll never break integration who fail to specify what they want. Facebook and Twitter did that and it was not received well by the developer community. The very first request to our API makes this required parameter clear in an error response and once it’s handled, it’s never thought about again. As you said, proxies today handle it just fine. I’ve also read that we can drop the “X-” convention as we’re not thinking our custom header will ever be on the road to being a globally accepted.
Use a custom HTTP Header especially when versioning is required at an API Service level and not on a Resource level.
I recommend implementing the Approach #3 Versioning through custom request header, we don’t break the resource and feature maintenance principles which occurs in URI versioning. In this way, we can integrate the versioning built in with web API without interrupting the consumers who wants to access old versions. Consumer never faces the complexity of versioning in the URI instead they specify it in request header but more over if they fail to specify the version at least the default version will send the response. Thus, avoids the URI conflicts of unreachable routes.
Library for API versioning support in Microsoft ASP Web API is available as a NuGet package. To install ASP Web API versioning support, run the following command in the Package Manager Console.
PM > Install-Package SDammann. WebApi. Versioning - Version 2.8.0.
Higher versioned GET methods cannot be accessed via browser. Instead it requires a web debugging tool like Fiddler to construct the request header with appropriate API-version number.
This approach can be quite problematic when you are using API Gateways. When you send the “api-version” header, it can cause some misleading to which API exactly you are referring to – the API Service that is your API Gateway (that can be versioned by it’s own) or the web API Service that should get the call from the API Gateway.

No comments:

Post a Comment