Voltar ao blogue
Guias
Sorin-Gabriel Marica7 de dezembro de 202210 min de leitura

Aprenda a usar o Node-Fetch do NPM para efetuar pedidos HTTP no Node.js

Aprenda a usar o Node-Fetch do NPM para efetuar pedidos HTTP no Node.js

Introdução à API Node-Fetch

Antes de começar a falar sobre a API Node-Fetch, devo dar-vos uma breve explicação sobre o que é um pedido HTTP. O objetivo de um pedido HTTP é recuperar informações de URLs em toda a Internet. Um exemplo simples de um pedido HTTP é aceder a um site.

Embora, há muito tempo, as solicitações HTTP fossem feitas utilizando objetos XMLHttpRequest ou XHR, atualmente todos os navegadores modernos suportam a API Fetch em JavaScript. Isto permite aos programadores efetuar as solicitações com uma sintaxe muito mais simples e elegante. No entanto, a API Fetch esteve ausente durante muito tempo da linguagem de servidor Node.JS, dando espaço para que outros pacotes personalizados assumissem essa funcionalidade, tais como: Axios, GOT e muitos outros.

O Node-Fetch é o equivalente à API Fetch do JavaScript e agora está finalmente disponível também no Node.JS.

Requisitos prévios para utilizar a API Node-Fetch

Em primeiro lugar, uma vez que este é um tutorial sobre o Node.JS, terá, naturalmente, de ter o Node.JS instalado. Se ainda não o tiver, pode descarregá-lo e instalá-lo a partir deste link.

O Node.js lançou o suporte experimental à API Fetch apenas a partir da versão 17.5. Por isso, terá de ter, pelo menos, a versão 17.5 do Node.js. Além disso, terá de utilizar o –experimental-fetch ao executar os seus scripts.

Se tiver uma versão mais antiga do Node.JS, pode utilizar o pacote «n» para atualizar para a versão mais recente. O «n» é um pacote do npmjs cujo único objetivo é permitir alternar entre as versões do Node.JS e do npm. Para o instalar e atualizar para a versão mais recente, siga estes passos:

npm install -g n
n mais recente

A OO comando «test» irá instalar a versão mais recente do Node.js. Para verificar a sua versão do Node.js, basta executar este comando:

node –versão

Como utilizar o Node-Fetch

Fazer uma solicitação HTTP em qualquer linguagem de programação é uma operação assíncrona, uma vez que a receção da resposta à solicitação demora algum tempo. Existem duas abordagens no que diz respeito à forma como se pode utilizar operações assíncronas. Pode optar por aguardar a resposta e, em seguida, continuar com o seu código, ou executar o seu código em paralelo.

O Node-Fetch suporta chamadas de função síncronas e assíncronas.

Solicitações GET no Node-Fetch

Para efetuar um pedido GET simples e extrair o corpo da resposta, pode utilizar o código abaixo:

fetch('https://www.webscrapingapi.com/')

    .then((response) => response.text())

    .then((body) => {

        console.log(body);

    });

Para executar este código, deve guardá-lo num ficheiro chamado node-fetch-example.js e executá-lo a partir da mesma pasta utilizando este comando: node --experimental-fetch node-fetch-example.js. Note que, ao executá-lo, receberá um aviso a indicar que «A API Fetch é uma funcionalidade experimental». Isto é normal, uma vez que se trata de uma funcionalidade experimental à data da redação deste artigo.

O VS Code apresenta um exemplo de pedido de recuperação com uma saída no terminal a alertar que a API Fetch é experimental

O trecho de código anterior não espera que o pedido termine antes de continuar a sua execução. Isto significa que qualquer código abaixo deste começará a ser executado imediatamente, sem esperar que a recuperação termine. Por exemplo, se adicionar um console.log(“Something”); abaixo do código, ao executar o script, a saída ficará assim:

Saída do terminal do VS Code a apresentar um resultado de registo da consola juntamente com um aviso experimental da API Fetch

Para explicar melhor o código acima, poderá reparar que utilizamos a função «then» duas vezes. O primeiro «then» será executado quando recebermos uma resposta da solicitação HTTP, e o que faz é associar essa resposta ao conteúdo da método response.text() (que devolve o corpo da resposta). Mas, o response.text() também é assíncrono e, por isso, precisamos de esperar pela sua resposta no segundo «then», onde body é igual ao resultado da promessa de response.text().

Também pode chamar a API fetch utilizando o await, tal como fazemos no exemplo seguinte:

(async () => {

    const response = await fetch('https://webscrapingapi.com');

    const body = await response.text();

    console.log(body);

})();

Isto fornece uma explicação ainda mais clara sobre como funciona a API Fetch e quais são as promessas pelas quais é necessário aguardar. Mais adiante neste artigo, utilizaremos a API Fetch com o `await`, uma vez que isso nos permite manter uma sintaxe mais clara no código.

Enviar cabeçalhos na solicitação

Outra funcionalidade de que irá precisar ao enviar pedidos é a possibilidade de definir os cabeçalhos do pedido que está a efetuar. Para tal, pode adicionar os cabeçalhos no segundo parâmetro da API fetch, da seguinte forma:

(async () => {

    const response = await fetch('http://httpbin.org/headers', {

        headers: {

            'my-custom-header': 'my-header-value'

        }

    });

    const body = await response.text();

    console.log(body);

})();

Além dos cabeçalhos, existem muitas outras opções que pode enviar no segundo parâmetro da API fetch. Para ver todas elas, consulte a documentação da API fetch (a utilizada no lado do cliente).

Pedidos POST no Node-Fetch

Outra opção importante da API Fetch é a opção «method». Esta especifica o método que está a utilizar para o pedido HTTP. Existem 5 métodos que pode utilizar: GET, POST, PUT, PATCH e DELETE, mas, destes, os dois primeiros são os mais utilizados (GET e POST). Por predefinição, se não for especificado nenhum método, o Node-Fetch utilizará o GET.

Para efetuar um pedido POST utilizando o Node-Fetch, pode utilizar este trecho de código:

(async () => {

    const response = await fetch('http://httpbin.org/post', {

        method: 'POST',

        body: JSON.stringify({

            'key': 'value'

        })

    });

    const body = await response.text();

    console.log(body);

})();
Exemplo de código que envia um pedido POST com JSON e saída do terminal que mostra a resposta JSON recebida

O que poderá notar aqui é que utilizamos o JSON.stringify para enviar o corpo da solicitação. Isto deve-se ao facto de a API Fetch enviar o corpo como uma cadeia de caracteres, em vez de um objeto, ao contrário do que fazem outras bibliotecas, como o axios.

A API Fetch também abrange todos os outros métodos de solicitação.

Gestão de erros no Node-Fetch

É essencial tratar os erros ao efetuar pedidos HTTP, uma vez que nunca se pode contar com a disponibilidade permanente de um serviço de terceiros. Como boa prática, deve sempre tratar os erros, para evitar que a sua aplicação ou script deixe de funcionar caso o endereço URL para o qual está a enviar o pedido fique indisponível.

O tratamento de erros no node-fetch pode ser feito envolvendo o código numa sintaxe simples de try-catch. Aqui está um exemplo de como fazê-lo ao utilizar o await:

(async () => {

    try {

        const response = await fetch('[INVALID_URL]');

        const responseBody = await response.text();

    } catch (error) {

        console.log(error.message);

    }

})();

Se preferir utilizar o `fetch` sem o `await`, pode adicionar um `catch` ao seu código da seguinte forma:

fetch('[INVALID_URL]')

    .then((response) => response.text())

    .then((body) => {

        console.log(body);

    })

    .catch((error) => {

        console.log(error.message);

    });

Casos de utilização do Node-Fetch

A realização de pedidos HTTP pode ser útil de várias formas, uma vez que permite obter novas informações de diferentes serviços e extrair dados de uma forma bastante elegante e simples. Existem alguns casos de utilização que iremos explorar nos parágrafos seguintes.

Utilize o Node-Fetch para pedidos de API

Foto em grande plano de alguém a escrever «USE APIs» num quadro branco, com uma seta a apontar para o texto

Ao programar, muitas vezes pode ser necessário utilizar uma API. Isto deve-se ao facto de poder ser necessário obter dados específicos de uma fonte de backend diferente e, em seguida, processá-los ou atualizá-los. Um bom exemplo seria uma API com 4 endpoints que permite criar, ler, atualizar e eliminar utilizadores (operações CRUD) numa base de dados de backend a partir de outro servidor.

Muitas vezes, uma API deste tipo necessita de autenticação para impedir que fontes não autorizadas a utilizem e alterem os dados em seu benefício. As solicitações HTTP dispõem de vários métodos de autenticação. Um dos mais comuns é a utilização de uma chave de API, em que o fornecedor da API lhe atribui uma chave que só você deve conhecer, e os pontos de extremidade da API só funcionam quando é enviada a chave correta.

Outro método através do qual uma API pode ser protegida é a autenticação básica. Isto significa que, para aceder à API, terá de enviar um cabeçalho com uma cadeia de caracteres codificada em base64 no formato «nome de utilizador:palavra-passe». Aqui está um exemplo de como pode utilizar a autenticação básica numa solicitação POST:

(async () => {

    const response = await fetch('http://httpbin.org/post', {

        method: 'POST',

        headers: {

            "Authorization": `Basic ${btoa('login:password')}`

        },

        body: JSON.stringify({

            'key': 'value'

        })

    });

    const body = await response.text();

    console.log(body);

})();

Utilize o Node-Fetch para a extração de dados da Web

O web scraping é uma forma de extrair conteúdo de sites e analisá-lo, de modo a reter apenas os dados necessários, que poderá utilizar como desejar. Uma boa biblioteca do npmjs que pode utilizar para facilitar a análise dos dados é a cheerio. Esta biblioteca permite-lhe consultar HTML estático, uma vez obtido através da API fetch, da mesma forma que o faria a partir de JavaScript ou jQuery.

Eis um exemplo de como obter o título de uma página utilizando a API Fetch e o Cheerio:

const cheerio = require("cheerio");

(async () => {

    const response = await fetch('https://www.webscrapingapi.com/');

    const responseBody = await response.text();

    const $ = cheerio.load(responseBody);

    console.log($('title').first().text());

})();

O exemplo acima deve devolver «WebScrapingAPI | All-In-One Scraping API», uma vez que este é o título da página (o texto que aparece na parte superior da janela do seu navegador). Para explicar melhor, usamos o fetch para obter o código-fonte da página HTML em https://www.webscrapingapi.com/ e usamos o cheerio para analisar esse conteúdo. Para saber mais sobre o cheerio, pode consultar a documentação aqui 

A recolha de informações de outros sites pode ser útil de várias formas. Por exemplo, as informações recolhidas podem ser utilizadas para criar um conjunto de dados de treino para um modelo de aprendizagem automática ou para criar uma ferramenta de comparação de preços que extrai dados de várias fontes e, em seguida, os compara.

Embora o exemplo acima funcione bem, a API Fetch pode nem sempre ser a melhor opção quando se trata de extração de dados. Isto porque os sites modernos apresentam atualmente o seu conteúdo através de JavaScript e utilizam captchas ou outros métodos para impedir que os seus dados sejam extraídos. A API Fetch funciona como um simples comando CURL para o URL indicado e recupera o conteúdo estático que a página apresenta quando é carregada, sem qualquer renderização de JavaScript.

Para extrair dados e, ao mesmo tempo, executar o código JavaScript na página, poderá querer explorar alternativas como o Puppeteer, conforme descrito neste artigo sobre extração avançada. No entanto, se não quiser passar por todo esse trabalho, pode utilizar a WebScrapingAPI, uma API criada especificamente para esta tarefa, que resolve todos esses problemas (incluindo a deteção de bots) e oferece um período de teste gratuito com todas as funcionalidades incluídas. 

Resumo

Resumindo, a boa notícia é que a tão esperada API Fetch está finalmente disponível no Node.js, embora, por enquanto, se encontre apenas na fase de funcionalidade experimental (à data da redação deste artigo). Embora já fosse possível efetuar pedidos no Node.js anteriormente, a única forma de o fazer era através dos objetos XMLHttpRequest/XHR ou de um dos muitos pacotes disponíveis, como o Axios ou o GOT.

Esta alteração tornará o JavaScript do lado do cliente e o Node.js do lado do servidor mais semelhantes, uma vez que esta funcionalidade já estava disponível e era suportada por todos os navegadores modernos no JavaScript do lado do cliente.

Fazer pedidos HTTP pode ser útil de várias formas, como ao utilizar uma API ou extrair dados de um site. Embora os outros pacotes npm continuem a ser uma opção e continuem a ser utilizados em projetos antigos, utilizar o fetch é a melhor solução para o futuro. Isto irá melhorar a legibilidade do código Node.js e facilitará ainda mais a transição do front-end para o back-end.

Sobre o autor
Sorin-Gabriel Marica, Desenvolvedor Full-Stack na WebScrapingAPI
Sorin-Gabriel MaricaDesenvolvedor Full-Stack

Sorin Marica é engenheiro Full Stack e DevOps na WebScrapingAPI, onde desenvolve funcionalidades do produto e mantém a infraestrutura que garante o bom funcionamento da plataforma.

Comece a construir

Pronto para expandir a sua recolha de dados?

Junte-se a mais de 2.000 empresas que utilizam a WebScrapingAPI para extrair dados da Web à escala empresarial, sem quaisquer custos de infraestrutura.