- Quando uma API web pública usa ao mesmo tempo um nome como Product API e o caminho
/api/v1, a versão semântica da própria API e sua estrutura podem ficar desalinhadas - Ao usar em paralelo o caminho
/v1/emajor.minor.patch, rotas e o contrato da API acabam se misturando, e o primeiro número da versão semântica fica preso à URL - Mudanças que quebram compatibilidade passam a exigir um novo caminho e rotas de proxy reverso, fazendo com que as informações de contrato fiquem espalhadas entre a URL e o número da versão
- Se APIs posteriores forem criadas ao mesmo tempo, a API existente fica, na prática, presa ao
v1, e depois, em mudanças incompatíveis, o significado do nome e do caminho se torna ambíguo - Trata-se da preocupação em encontrar abordagens de versionamento de APIs web públicas que repetidamente incomodam e buscar princípios de design melhores
Quer continuar recebendo tópicos de tecnologia selecionados?
Siga o canal no Telegram. @GeekNewsBrasil
1 comentários
Opiniões no Lobste.rs
Colocar
/v1/na URL é, na verdade, uma das grandes vantagens. Porque isso obriga você a não quebrar a API para os usuários até desativar o endpointEvolving HTTP APIs e outros textos do mesmo autor trazem conselhos úteis
Em geral, colocamos
/v1/,/v2/etc. em cada rota para indicar mudanças incompatíveis. Se for uma API pública em operação, e não uma tentativa de definir um padrão que funcione em vários hosts, quase não há motivo para fazer versionamento semântico completo (semantic versioning)O versionamento semântico existe para que outros desenvolvedores possam atualizar dependências com confiança sem precisar passar 20 minutos lendo changelogs, mas numa API em produção as pessoas não podem escolher quando adotar uma nova versão minor ou de correção
O que conta como mudança incompatível é alterar um comportamento documentado ou quebrar clientes existentes que dependem desse comportamento documentado. Há lugares que também tratam mudanças em comportamentos não documentados como quebra, mas isso traz muitos riscos
No Google, fazem assim: AIP-185: API Versioning, AIP-180: Bacwards compatibility
Esses documentos de design parecem bem específicos da forma como o Google trabalha, mas eu os venho usando como referência ao projetar APIs, e algumas ideias dali foram muito úteis
Em geral, acho que toda API deveria tentar minimizar ao máximo as mudanças incompatíveis. Por exemplo, se você quiser renomear uma propriedade, parece melhor adicionar o novo nome em duplicidade do que remover a propriedade antiga
Ainda assim, a forma como o pessoal da Buttondown faz isso também é elegante. Eles definem migrações entre versões da API, assim o consumidor pode fixar sua versão da API por header, enquanto o provedor continua evoluindo o serviço
A resposta óbvia parece ser “o nome novo sempre tem prioridade”, mas isso pode falhar se o cliente fizer uma sequência de leitura-modificação-escrita e reenviar uma versão modificada de um objeto criado pelo servidor. Nesse caso, o cliente pode atualizar só a propriedade antiga e devolver a nova sem mexer nela
Parece que esse tipo de transformação também poderia ser usado para mapeamento de comportamento, mas, a menos que eu tenha deixado passar algo, isso não foi abordado
Idealmente, a versão deveria estar incluída no caminho, e novas versões deveriam ser de natureza adicional. Assim, a API da versão antiga poderia redirecionar internamente a requisição para uma versão mais nova da API, aplicando as transformações necessárias de entrada e saída
Depois de alguns anos, quando ninguém mais estiver usando uma versão antiga, ela pode ser removida, e a rota
/v1/passa a retornar erroHá um tempo li um pouco sobre fazer versionamento de API com negociação de conteúdo via header
Accept. Se alguém já fez versionamento de API desse jeito, eu gostaria de saber como foi a experiênciaPela minha experiência, versionamento por recurso ou versionamento global foram as abordagens mais intuitivas. Para descontinuação, usar o header de resposta HTTP
Deprecation(RFC 9745) e, no fim, retornar algo como410 Gonepara endpoints antigos parece uma forma razoável de levar clientes a migrarem para a nova versãoAlém disso, também fico realmente curioso se alguém já construiu uma API evolutiva. Quero dizer, uma abordagem em que requisições para versões antigas são traduzidas internamente para requisições da versão nova da API e, depois que os clientes migram ou passa certo tempo, a versão antiga é de fato removida