Solucionado (ver solução)
Solucionado
(ver solução)
14
respostas

Consumindo API que possui sistema de autenticação

Construi uma API com o framework Django Rest. Essa API gera uma consulta de livros que eu tenho na minha estante.

Quero fazer um site simples que consuma essa API usando JS e HTML. Estou usando o Fetch para ter acesso à API, masnão estou conseguindo consumir essa API. Tentei colocar a autenticação e depois tirei e mesmo assim não está funcionando.

Já implementei inclusive o Live Server para evitar problema de CORS.

Seguem os códigos:


function listaLivrosAPI() {
    let headers = new Headers();

    headers.append('Content-Type', 'application/json');  

    headers.append('Access-Control-Allow-Origin', 'http://127.0.0.1:8000');



    return fetch('http://localhost:8000/livros', {
        mode: 'no-cors',    
        method: 'GET', 
        headers: headers  
      })
      .then(response => response.json())
      .then(json => json)
      .catch(error => console.log('Authorization failed : ' + error.message));
  }

Erro:

listaDeLivros.js:4 Uncaught TypeError: listaLivros.map is not a function
    at listaDeLivros.js:4
(anonymous) @ listaDeLivros.js:4
14 respostas

Fala ai Raul, tudo bem? Qual é o retorno do endpoint http://localhost:8000/livros e em qual momento você faz listaLivros.map?

Fico no aguardo.

Olá, a API que criei retorna um objeto contendo:

{
    'titulo_livro': 'Mistborn',
    'autor_livro': 'Brandon Sanderson',
    'editora_livro': 'Leya',
    'valor_livro': '80.00'
}

Que é acessada nesse endereço http://127.0.0.1:8000/livros/

Quanto ao MAP seguem as 2 funções que eu crio:

1-


function listaLivrosAPI() {
    let headers = new Headers()

    headers.append('Content-Type', 'application/json');    
    headers.append('Access-Control-Allow-Origin', 'http://localhost:5500/');



    return fetch('http://localhost:8000/livros/', {
        mode: 'no-cors',  
        async:true,  
        method: 'GET', 
        headers: headers  
      })
      .then(response => response.json())

  }

2-

const listaLivros = listaLivrosAPI()


listaLivros.then(dados => dados.map(dado=>{
    const tabela = document.querySelector('[data-tabela]');
    const tbody = document.createElement('tbody');
    tbody.innerHTML = `
        <tr>
            <td>${dado.titulo_livro}</td>
            <td>${dado.autor_livri}</td>
            <td>${dado.editora_livro}</td>
            <td>${dado.valor_livro}</td>
        </tr>
    `
    tabela.appendChild(tbody)

    })
);

Baixei o live server pelo node tbm e continua dando erro:

consumindoAPI.js:17 Uncaught (in promise) SyntaxError: Unexpected end of input
    at consumindoAPI.js:17

Fala Raul, olhando os códigos os mesmos parecem estar ok, mas, posso deixar passar algum detalhe facilmente.

Sendo assim, posso te pedir um favor? Compartilha o projeto completo comigo, assim eu consigo simular o problema por aqui e analisá-lo com mais calma.

Pode compartilhar através do Github ou Google Drive (zipado).

Fico no aguardo.

Minha idéia é fazer 2 mini projetos baseado no curso de SPA e no do IndexedDB do Flávio Almeida. Um usando classes + indexedDB e o outro consumindo dados de uma API em Django Rest que fiz recentemente, para por conhecimentos em prática(Django e JS).

Só que no inicio do curso de SPA ele conseguia consumir a API somente usando o Fetch e o live server para não dar o CORS, sem o uso do webpack e suas configurações. Ainda nem modularizei, nem fiz o webpack, só fiz o CRU mesmo.

Segue GIT da API:

https://github.com/Raul-Pinheiro/ProjPessoal-ListaLivrosAPI-DjangoRest

Segue GIT do Portal:

https://github.com/Raul-Pinheiro/ProjetoPessoa-PortalLivros

Fala Raul, muito bom, essas práticas e mini projetos à parte são muito bom e com certeza vão te trazer vários novos conhecimentos.

Abraços e bons estudos.

Mas tá dando erro ainda :(. O estranho é que testei a API no Postman e tava aparecendo os dados, mas usando o fetch, não aparece os dados que criei.

Fala Raul, tente logar a resposta para ver o que foi retornado da API para o front, algo assim:

return fetch('http://localhost:8000/livros/', {
    mode: 'no-cors',  
    async:true,  
    method: 'GET', 
    headers: headers  
}).then(response => response.json()).then(console.log)

Veja o que será impreso como retorno do response.json.

Fico no aguardo

Segue o erro: Fiz apenas uma alteração, modularizei tudo.

opaque
consumindoAPI.js:20 SyntaxError: Unexpected end of input
    at consumindoAPI.js:18
listaDeLivros.js:7 Uncaught (in promise) TypeError: Cannot read property 'map' of undefined
    at listaDeLivros.js:7

Fala Raul, acho que vou precisar simular o problema por aqui para analisá-lo com mais calma.

Consegue subir no Github ou Google Drive (zipado) uma pasta com o front e back?

Fico no aguardo.

Vou te falar que não sei fazer esse zip pelo GIT... só faço o básico com ele, infelizmente. Como eu posso zipar pelo git? Não seria melhor fazer um git tag?

Fala Raul, na verdade são duas ideias diferente, uma seria criar um repositório no Github que dentro dele tem o front e back separados em outras duas pastas.

A ideia seria você compactar a pasta via Windows ou qualquer outro S.O e subir no Google Drive esse .zip.

Abraços.

https://drive.google.com/file/d/1okpuP9xlMYz4i0Pt9ohKeWZY9SDzrtvj/view?usp=sharing

Segue o link. Tem o front (portalLivros) e o back (livrosAPI): Para rodar o back é só digitar: python manage.py runserver na pasta do projeto, se tiver o python 3 instalado.

solução!

O código ficou assim para funcionar...

Front:

function getDados(){

    return fetch("http://127.0.0.1:8000/livros/",{
      method:'GET',
      headers: {
        'Content-Type': 'application/json',
        'Authorization':'Basic '+ window.btoa('user:senha')
        },          

    })
    .then(resp=>resp.json())
}

E no backend Django Rest tive que instalar uma lib chamada CORSHEADERS:

CORS_ALLOWED_ORIGINS = [
    "https://localhost:5500",
    "http://localhost:9000/",
]
CORS_ALLOW_ALL_ORIGINS = False
CSRF_TRUSTED_ORIGINS = [
    "https://localhost:5500",
]
CORS_ALLOW_CREDENTIALS=False

Fala Raul, muito bom, desculpe não ter tido tempo para responder antes.

Parabéns pela solução, sempre que precisar não deixe de criar suas dúvidas.

Abraços e bons estudos.