Estamos falando sobre escrever especificações de APIs há um bom tempo aqui no blog. RAML, Swagger e OpenAPI Specification já foram explorados, e com os dois últimos encontramos um ecossistema rico com ferramentas extremamente interessantes.
Há um outro simpático player no mercado, o API Blueprint, e o post de hoje é sobre essa prática ferramenta.
Um colega de trabalho, há muito tempo atrás, me apresentou o API Blueprint. Na ótica dele, um dos aspectos mais interessantes era a escrita utilizando Markdown.
Sim! É verdade! Claro que utilizando o formato/extensão específico há ganhos como syntax highlighting, mas ainda assim é possível escrever a especificação de uma API somente com Markdown, o que torna a leitura do documento mais amigável, e interoperável com ferramentas como o seu editor de textos, ou o próprio Github.
Para quem já tem um README.md
em seu repositório, ter um api.md
não parece ser
nenhum grande sacrifício. E dependendo do seu público alvo, ter a "documentação final gerada"
pode ser tão simples quanto compartilhar o link da especificação no Github.
A documentação oficial o define da seguinte forma:
(...) is simple and accessible to everybody involved in the API lifecycle. Its syntax is concise yet expressive. With API Blueprint you can quickly design and prototype APIs to be created or document and test already deployed mission-critical APIs.
Assim como os já citados RAML e Swagger, o API Blueprint é uma linguagem de design utilizada para descrever APIs. O seu propósito é o de encorajar o diálogo e colaboração, logo, uma ferramenta mais que ideal para adoção no seu processo de API-First.
Para ter os ganhos que citei anteriormente, o API Blueprint usa um "melhoramento" do Markdown chamado de MSON (Markdown Syntax for Object Notation). É com essa notação que utilizamos a síntaxe do Markdown para descrever estruturas de dados, heranças e recursos.
Voltando ao bom e velho exemplo do mini IMDB, vamos criar um arquivo api.md
e pôr a mão na massa.
Começamos por definir qual versão do API Blueprint utilizaremos, bem como descrevendo o nome da API e seu propósito:
FORMAT: A1
# Movies API
This is an API Blueprint example describing a movies API.
O #
, no Markdown, é associado a um "título de nível 1". Ou seja, o # Movies API
se convertido em HTML produziria um <h1>Movies API</h1>
.
Nesse caso, o #
produz o título da API. O #
também é utilizado para agrupar recursos, mas nesse caso, ele necessita da keyword
Group
:
FORMAT: A1
# Movies API
This is an API Blueprint example describing a movies API.
# Group Movies
Resources related to movies in the API.
O próximo passo é descrever o recurso e seus endpoints. Começaremos pelo
endpoint /movies
. Para descrever o recurso, utilizamos o ##
, já a ação
é representada através de 3 hashtags (###
):
(...)
## Movie collection [/movies]
### List all Movies [GET]
List movies in reverse order of publication.
- Response 200 (application/json)
Quando o recurso /movies
receber uma requisição GET
, ele responderá com
o status code 200
, e com o content-type
application/json
. Essa última
parte é descrita através da linha + Response 200 (application/json)
.
Podemos também descrever como será o payload dessa resposta.
É possível utilizar JSON Schema para descrever o payload de requisições e respostas. Como ilustrado nesse exemplo tirado da documentação oficial:
### Create a New Question [POST]
You may create your own question using this action. It takes a JSON object
containing a question and a collection of answers in the form of choices.
- Request (application/json)
- Body
{
"question": "Favourite language?"
"choices": [
"Swift",
"Objective-C"
]
}
- Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"question": {
"type": "string"
},
"choices": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 2
}
}
}
O JSON Schema é um vocabulário poderoso para anotar e validar documentos JSON. No entanto, ele pode "destoar" do resto do seu documento.
Há uma alternativa utilizando o próprio MSON. Através da seção ## Data structure
, conseguimos algo semelhante com o ilustrado acima.
(...)
## Data structures
### Movie
- id: 810b43d0-fc0d-4199-8a79-25b471c880bf (string, required)
- title: Avengers: Endgame (string, required)
- description (string)
Descrevemos a estrutura Movie
, informando o seu id
(string
e obrigatória),
title
e description
. Note que este último, além de não ser obrigatório, não
possui nenhum exemplo informado (como os dois outro campos).
Para associar a estrutura acima com a resposta de /movies
, utilizamos
Attributes
:
(...)
### List all Movies [GET]
List movies in reverse order of publication.
- Response 200 (application/json)
- Attributes (array[Movie])
(...)
Com ajuda do tipo array
, descrevemos o payload da resposta do endpoint.
No fim das contas, um JSON body e JSON Schema é gerado através dos
atributos MSON. Por isso do bloco Schema
, exibido na imagem acima.
Visite o tutorial do API Blueprint e veja como aplicar a especificação para os demais verbos HTTP.
O exemplo completo pode ser conferido aqui.
As imagens representando a especificação foram extraídas do plugin API Blueprint Viewer, para o VS Code.
Na página de Tools do site oficial é possível conhecer as diferentes ferramentas à disposição, que vão desde editores até mock servers.
Nesse quesito, uma das ferramentas que me conquistou foi o Dredd, que é utilizado para validar especificação, e funciona tanto com o API Blueprint quanto com o OpenAPI. Aliás, OpenAPI/Swagger ainda são "campeões" no quesito ferramentas disponíveis.
Pela característica do Markdown, e de ser relativamente mais barato de escrever, eu tive a oportunidade de utilizar o API Blueprint da seguinte forma:
A facilidade de escrita de documentos API Blueprint faz dele uma ótima opção e um player mais que interessante no cenário de specs REST. Um terreno ainda dominado pelo Swagger...
Até a próxima.