⚗️
Consumindo APIs com Elixir
  • Introdução
  • Sobre o autor
  • O valor desse livro
  • Introdução
    • Por que elixir?
    • Como ler este livro
    • Sobre o conteúdo do livro
  • Configurando ambiente
    • Instalando o Elixir
    • Criando um projeto
  • Construindo um cliente usando Tesla
    • Iniciando
    • Tesla
      • O que é o Tesla
      • Instalando Tesla
    • Criando o Client
    • Estruturando resposta
    • Estratégia de teste para requisições
    • Instalando Bypass
    • Mockando requisições do cliente com Bypass
    • Tratando dados da resposta
  • Problemas de API externa
    • Erro genérico
    • O que é o rate limit
    • Rate Limite de curta duração
      • Reexecutando uma requisição
    • Rate Limit de longa duração
      • Agendando uma nova tentativa de requisição
      • Configurações necessárias
      • Adicionando Ecto ao projeto
      • O que é o Oban
      • Instalando Oban
      • Criando uma requisição assíncrona
      • Configurando quantidade de tentativas no Oban
  • Compondo integrações
    • Level up
    • Marvel API
      • Criando uma conta
      • Lendo o endpoint de Comics
      • Criando o cliente da Marvel
        • Melhorando a segurança
      • Lidando com a resposta
    • Aproveitando ao máximo o Rate Limit
  • Em breve
    • WIP - Supervisor
    • WIP - OAuth
    • WIP - Cacheando requisições
Fornecido por GitBook
Nesta página

Isto foi útil?

  1. Compondo integrações
  2. Marvel API

Lendo o endpoint de Comics

AnteriorCriando uma contaPróximoCriando o cliente da Marvel

Atualizado há 1 ano

Isto foi útil?

A Marvel API nos disponibiliza alguns recursos legais, como obter personagens, historias em quadrinho, eventos, séries, entre outros.

Para ver todos os endpoints, só acessar o e teremos ali uma lista completa dos recursos e como devemos montar nossas requisições.

Em nosso estudo, utilizarei a listagem de Comics (revistas em quadrinhos)

Olhando apenas o básico temos essa estrutura

GET https://<url_base>/v1/public/comics

Temos aqui

Verbo

GET

Recurso

/v1/public/comics

URL base

?

Verbo

GET

Recurso

/v1/public/comics

URL base

https://gateway.marvel.com

Podemos agora montar nossa requisição e testala com o Tesla.

GET https://gateway.marvel.com/v1/public/comics

Convertendo

Tesla.get("https://gateway.marvel.com/v1/public/comics")

Podemos acessar nosso terminal iterativo e testar a requisição

iex -S mix   
Tesla.get("https://gateway.marvel.com/v1/public/comics")
iex(1)> Tesla.get("https://gateway.marvel.com/v1/public/comics")
{:ok,
 %Tesla.Env{
   method: :get,
   url: "https://gateway.marvel.com/v1/public/comics",
   query: [],
   headers: [
     {"connection", "keep-alive"},
     {"date", "Wed, 08 May 2024 17:57:08 GMT"},
     {"content-length", "68"},
     {"content-type", "application/json; charset=utf-8"}
   ],
   body: "{\"code\":\"MissingParameter\",\"message\":\"You must provide a user key.\"}",
   status: 409,
   opts: [],
   __module__: Tesla,
   __client__: %Tesla.Client{fun: nil, pre: [], post: [], adapter: nil}
 }}

Aqui temos nosso primeiro problema. Mesmo a API sendo publica, temos controle de quem está acessando. Nesse caso ele avisa que precisamos de um chave de usuário. E foi para isso que criamos uma conta na Marvel.

Vou nomear a minha como 12345, para facilitar o entendimento.

Verbo

GET

Recurso

/v1/public/comics

URL base

https://gateway.marvel.com

Api Key

12345

Vamos atualizar nossa chamada com o Tesla. Para passar esse dado, utilizaremos query params.

Tesla.get("https://gateway.marvel.com/v1/public/comics?apikey=12345")
iex(3)> Tesla.get("https://gateway.marvel.com/v1/public/comics?apikey=d3f934e3c9ccb6de467674e4fc7a3ead")
{:ok,
 %Tesla.Env{
   method: :get,
   url: "https://gateway.marvel.com/v1/public/comics?apikey=d3f934e3c9ccb6de467674e4fc7a3ead",
   query: [],
   headers: [
     {"connection", "keep-alive"},
     {"date", "Wed, 08 May 2024 18:06:59 GMT"},
     {"content-length", "64"},
     {"content-type", "application/json; charset=utf-8"}
   ],
   body: "{\"code\":\"MissingParameter\",\"message\":\"You must provide a hash.\"}",
   status: 409,
   opts: [],
   __module__: Tesla,
   __client__: %Tesla.Client{fun: nil, pre: [], post: [], adapter: nil}
 }}

Passamos do problema da user key. Mas caímos agora no problema do hash.

O hash na API da Marvel é uma encriptação simples usando MD5 que utiliza os dados

Nome
Descrição

TS

Uma string que servirá para termos unicidade nas requisições. Cada requisição deve ter um valor diferente.

Chave Publica

Que chamamos acima de api key

Chave privada

Uma chave extra para realizar a decrypt. Basicamente, a chave para abrir.

Marquei em amarelo a publica e rosa a privada.

Utilizaremos como TS, por hora, o numero 1. Simplesmente para seguir com os estudos.

Como chave privada, demonstrarei como 88888.

A regra para o hash é:

<TS>+<chave_privada>+<chave_publica>

Podemos criar isso pelo elixir, entrando no modo iterativo

:crypto.hash(:md5, "11234588888") |> Base.encode16()
iex(1)> :crypto.hash(:md5, "11234588888") |> Base.encode16()
"7EE341DFFE88E697114117AA51E1A210"

Vamos agora pegar esse valor e adicionar a nossa query param. Também devemos colocar o valor de TS em nosso query o mesmo informado na criação do hash.

Tesla.get("https://gateway.marvel.com/v1/public/comics?apikey=12345&hash=7EE341DFFE88E697114117AA51E1A210&ts=1")
iex(1)> Tesla.get("https://gateway.marvel.com/v1/public/comics?apikey=12345&hash=7EE341DFFE88E697114117AA51E1A210&ts=1")
{:ok,
 %Tesla.Env{
   method: :get,
   url: "https://gateway.marvel.com/v1/public/comics?apikey=d3f934e3c9ccb6de467674e4fc7a3ead&ts=1&hash=1d49870a0631827587878fcff98fa267",
   query: [],
   headers: [
     {"connection", "keep-alive"},
     {"date", "Wed, 08 May 2024 18:21:51 GMT"},
     {"etag", "60ddd4a67c6e3242fa2560dbb0035b3925d666ef"},
     {"content-length", "66553"},
     {"content-type", "application/json; charset=utf-8"}
   ],
   body: "{\"code\":200,\"status\":\"Ok\",\"copyright\":\"© 2024 MARVEL\",\"attributionText\":\"Data provided by Marvel. © 2024 MARVEL\",\"attributionHTML\":\"<a href=\\\"http://marvel.com\\\">Data provided by Marvel. © 2024 MARVEL</a>\",\"etag\":\"60ddd4a67c6e3242fa2560dbb0035b3925d666ef\",\"data\":{\"offset\":0,\"limit\":20,\"total\":60239,\"count\":20,\"results\":[{\"id\":82967,\"digitalId\":0,\"title\":\"Marvel Previews (2017)\",\"issueNumber\":0,\"variantDescription\":\"\",\"description\":\"\",\"modified\":\"2019-11-07T08:46:15-0500\",\"isbn\":\"\",\"upc\":\"75960608839302811\",\"diamondCode\":\"\",\"ean\":\"\",\"issn\":\"\",\"format\":\"\",\"pageCount\":112,\"textObjects\":[],\"resourceURI\":\"http://gateway.marvel.com/v1/public/comics/82967\",\"urls\":[{\"type\":\"detail\",\"url\":\"http://marvel.com/comics/issue/82967/marvel_previews_2017?utm_campaign=apiRef&utm_source=25a07f7adccf7328d3153451c26bd992\"}],\"series\":{\"resourceURI\":\"http://gateway.marvel.com/v1/public/series/23665\",\"name\":\"Marvel Previews (2017 - Present)\"},\"variants\":[{\"resourceURI\":\"http://gateway.marvel.com/v1/public/comics/82965\",\"name\":\"Marvel Previews (2017)\"},{\"resourceURI\":\"http://gateway.marvel.com/v1/public/comics/82970\",\"name\":\"Marvel Previews (2017)\"},{\"resourceURI\":\"http://gateway.marvel.com/v1/public/comics/82969\",\"name\":\"Marvel Previews (2017)\"},{\"resourceURI\":\"http://gateway.marvel.com/v1/public/comics/74697\",\"name\":\"Marvel Previews (2017)\"},{\"resourceURI\":\"http://gateway.marvel.com/v1/public/comics/72736\",\"name\":\"Marvel Previews (2017)\"},{\"resourceURI\":\"http://gateway.marvel.com/v1/public/comics/75668\",\"name\":\"Marvel Previews (2017)\"},{\"resourceURI\":\"http://gateway.marvel.com/v1/public/comics/65364\",\"name\":\"Marvel Previews (2017)\"},{\"resourceURI\":\"http://gateway.marvel.com/v1/public/comics/65158\",\"name\":\"Marvel Previews (2017)\"},{\"resourceURI\":\"http://gateway.marvel.com/v1/public/comics/65028\",\"name\":\"Marvel Previews (2017)\"},{\"resourceURI\":\"http://gateway.marvel.com/v1/public/comics/75662\",\"name\":\"Marvel Previews (2017)\"},{\"resourceURI\":\"http://gateway.marvel.com/v1/public/comics/74320\",\"name\":\"Marvel Previews (2017)\"},{\"resourceURI\":\"http://gateway.marvel.com/v1/public/comics/73776\",\"name\":\"Marvel Previews (2017)\"}],\"collections\":[],\"collectedIssues\":[],\"dates\":[{\"type\":\"onsaleDate\",\"date\":\"2099-10-30T00:00:00-0500\"},{\"type\":\"focDate\",\"date\":\"2019-10-07T00:00:00-0400\"}],\"prices\":[{\"type\":\"printPrice\",\"price\":0}],\"thumbnail\":{\"path\":\"http://i.annihil.us/u/prod/marvel/i/mg/b/40/image_not_available\",\"extension\":\"jpg\"},\"images\":[],\"creators\":{\"available\":1,\"collectionURI\":\"http://gateway.marvel.com/v1/public/comics/82967/creators\",\"items\":[{\"resourceURI\":\"http://gateway.marvel.com/v1/public/creators/10021\",\"name\":\"Jim Nausedas\",\"role\":\"editor\"}],\"returned\":1},\"characters\":{\"available\":0,\"collectionURI\":\"http://gateway.marvel.com/v1/public/comics/82967/characters\",\"items\":[],\"returned\":0},\"stories\":{\"available\":2,\"collectionURI\":\"http://gateway.marvel.com/v1/public/comics/82967/stories\",\"items\":[{\"resourceURI\":\"http://gateway.marvel.com/v1/public/stories/183698\",\"name\":\"cover from Marvel Previews (2017)\",\"type\":\"cover\"},{\"resourceURI\":\"http://gateway.marvel.com/v1/public/stories/183699\",\"name\":\"story from Marvel Previews (2017)\",\"type\":\"interiorStory\"}],\"returned\":2},\"events\":{\"available\":0,\"collectionURI\":\"http://gateway.marvel.com/v1/public/comics/82967/events\",\"items\":[],\"returned\":0}},{\"id\":82965,\"digitalId\":0,\"title\":\"Marvel Previews (2017)\",\"issueNumber\":0,\"variantDescription\":\"\",\"description\":\"\",\"modified\":\"2019-08-21T17:11:27-0400\",\"isbn\":\"\",\"upc\":\"75960608839302611\",\"diamondCode\":\"JUL190068\",\"ean\":\"\",\"issn\":\"\",\"format\":\"\",\"pageCount\":152,\"textObjects\":[],\"resourceURI\":\"http://gateway.marvel.com/v1/public/comics/82965\",\"urls\":[{\"type\":\"detail\",\"url\":\"http://marvel.com/comics/issue/82965/marvel_previews_2017?utm_campaign=apiRef&utm_source=25a07f7adccf7328d3153451c26bd992\"}],\"series\":{\"resourceURI\":\"http://gateway.marvel.com/v1/public/series/23665\",\"name\":\"Marvel Previews (2017 - Present)\"},\"variants\":[{\"resourceURI\":\"http://gateway.marvel.com/v1/public/comics/82967\",\"name\":\"Marvel Previews (2017)\"},{\"resourceURI\":\"http://gateway.marvel.co" <> ...,
   status: 200,
   opts: [],
   __module__: Tesla,
   __client__: %Tesla.Client{fun: nil, pre: [], post: [], adapter: nil}
 }}

Pronto, estamos com todo acesso necessário para utilizar a API da Marvel. Bora escrever nosso cliente.

Vamos extrair as informações para conseguir realizar a requisição igual como fizemos em nosso .

Mas esta faltando a URL base de nossa requisição. Para essa informação, podemos acessar o . e veremos que nossa base é https://gateway.marvel.com/

e iremos encontrar a chave necessária. Sua API Key é sua chave pública. Marquei de amarelo.

As chaves encontramos na .

serviço de cafés quentes
General API Information
Acesse sua conta de desenvolvedor
conta de de desenvolvedor
link da documentação
https://developer.marvel.com/docs#!/public/getComicsCollection_get_6
https://developer.marvel.com/account