12. As funções HTTP em JavaScript

12.1. Escolha de uma biblioteca HTTP
Escolhemos aqui duas bibliotecas:
O EcmaScript 6 possui, por padrão, uma função chamada HTTP, que não está implementada pelo [node.js] (setembro de 2019). Existe uma biblioteca chamada [node-fetch] que permite utilizar a função [fetch] no Node. Essa biblioteca utiliza certas API específicas do [node.js]. Um código [node-fetch] pode, portanto, não ser 100% transportável para um ambiente que não seja [node], como, por exemplo, um navegador;
Além disso, existe uma biblioteca chamada [axios] dedicada a consultas HTTP, compatível tanto com [node.js] quanto com navegadores. É essa biblioteca que utilizaremos no final.
Apresentaremos um mesmo script escrito com essas duas bibliotecas para mostrar que o processo de codificação com elas é semelhante.
12.2. Configuração de um ambiente de trabalho
12.2.1. Instalação do servidor de cálculo de impostos
Por fim, vamos escrever um aplicativo web com a seguinte arquitetura:

JS: JavaScript
O código JavaScript é do lado do cliente:
- de um serviço de páginas ou fragmentos estáticos;
- de um serviço jSON;
O código JavaScript é, portanto, um cliente jSON e, como tal, pode ser organizado em camadas [UI, métier, dao] (UI: Interface do Usuário), assim como nossos clientes jSON escritos em PHP.
O servidor será o de cálculo de impostos, do qual já escrevemos 13 versões. Vamos escrever uma 14ª. Portanto, começamos duplicando, no NetBeans, a pasta da versão 13 na pasta da versão 14:

- em [6], modificamos o arquivo [config.json] da versão 14 da seguinte maneira:
{
"databaseFilename": "Config/database.json",
"rootDirectory": "C:/myprograms/laragon-lite/www/php7/scripts-web/impots/version-14",
"relativeDependencies": [
"/Entities/BaseEntity.php",
"/Entities/Simulation.php",
...
"vues": {
"vue-authentification.php": [700, 221, 400],
"vue-calcul-impot.php": [200, 300, 341, 350, 800],
"vue-liste-simulations.php": [500, 600]
},
"vue-erreurs": "vue-erreurs.php"
}
- na linha 3, alteramos a pasta raiz do aplicativo;
Para acessar esse servidor, é necessário iniciar os serviços [Laragon].
Feito isso, podemos testar com o [Postman] (ver artigo no link), essa nova versão do servidor, idêntica, por enquanto, à versão 13. Podemos utilizar o conjunto de consultas usado para testar a versão 12 do servidor de cálculo de impostos:

- no [1-4], usar a consulta [init-session-700] para inicializar uma sessão jSON;
- em [4-5], substitua [version-12] por [version-14] para testar a versão 14 do projeto;
- na execução, devemos receber a resposta jS0N [6] do servidor;
A versão 14 do servidor já está operacional. Teremos que modificá-la ligeiramente. Lembramos o API deste servidor:
Ação | Função | Contexto de execução |
init-session | Serve para definir o tipo (json, xml, html) das respostas desejadas | Solicitação GET main.php?action=init-session&type=x pode ser enviada a qualquer momento |
autenticar-usuário | Autoriza ou não um usuário a fazer login | Solicitação POST main.php?action=autenticar-usuário A solicitação deve conter dois parâmetros enviados por POST [user, password] Só pode ser emitida se o tipo da sessão (json, xml, html) for conhecido |
calcular-imposto | Realiza uma simulação de cálculo de imposto | Solicitação POST main.php?action=calcular-imposto A solicitação deve conter três parâmetros enviados via POST: [marié, enfants, salaire] Só pode ser emitida se o tipo da sessão (json, xml, html) for conhecido e o usuário estiver autenticado |
listar-simulações | Solicita a exibição da lista de simulações realizadas desde o início da sessão | Solicitação GET main.php?action=lister-simulations A solicitação não aceita nenhum outro parâmetro Só pode ser emitida se o tipo da sessão (json, xml, html) for conhecido e o usuário estiver autenticado |
excluir-simulação | Exclui uma simulação da lista de simulações | Consulta GET main.php?action=lister-simulações&número=x A solicitação não aceita nenhum outro parâmetro Só pode ser enviada se o tipo da sessão (json, xml, html) for conhecido e o usuário estiver autenticado |
fim-sessão | Encerra a sessão de simulações. | Tecnicamente, a sessão web anterior é excluída e uma nova sessão é criada Só pode ser emitida se o tipo da sessão (json, xml, html) for conhecido e o usuário estiver autenticado |
12.2.2. Instalação das bibliotecas HTTP do cliente JavaScript
Inicialmente, trabalharemos com a seguinte arquitetura:

- no [1], um script de console [node.js] faz uma solicitação HTTP ao servidor jSON de cálculo do imposto;
- em [4], ele recebe essa resposta e a exibe no console;
No exemplo nº 1, utilizaremos as bibliotecas [node-fetch] e [axios]; depois, manteremos apenas a [axios] para os exemplos seguintes. Agora, instalaremos essas duas bibliotecas JavaScript a partir do terminal de [VSCode]:

Também utilizaremos a biblioteca [qs], que permite a codificação URL de uma sequência de caracteres. Vale lembrar que essa codificação é usada para codificar os parâmetros de uma solicitação HTTP, GET ou POST.

12.3. script [fetch-01]
O script [fetch-01] utiliza a biblioteca [node-fetch] para inicializar uma sessão jSON com o servidor de cálculo de impostos. Seu código é o seguinte:
'use strict';
// importações
import fetch from 'node-fetch';
import qs from 'qs';
import { sprintf } from 'sprintf-js';
import moment from 'moment';
// URL básico do servidor de cálculo de impostos
const baseUrl = 'http://localhost/php7/scripts-web/impostos/versão-14/main.php?';
// inicialização da sessão
async function initSession() {
// opções da consulta HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
timeout: 2000
};
// execução da consulta HTTP [get /main.php?action=init-session&type=json]
let débutFetch;
try {
// solicitação assíncrona — [fetch] retorna uma promessa
débutFetch = moment(Date.now());
const response = await fetch(baseUrl + qs.stringify({
action: 'init-session',
type: 'json'
}), options);
// [response] é a resposta completa HTTP do servidor (cabeçalhos HTTP + a própria resposta)
// exibimos essa resposta para ver sua estrutura
console.log(sprintf("réponse fetch formatée en json,=%j, %s", response, heure(débutFetch)));
console.log("réponse fetch en javascript=", response);
// é possível acessar os cabeçalhos HTTP
console.log("entêtes de la réponse=", response.headers);
// se a resposta for do tipo application/json, a resposta JSON do servidor é obtida com a função assíncrona [response.json()]
// nesse caso, o código chamador obtém um objeto [Promise]
// [await] permite obter a resposta [json] do servidor em vez de sua promessa
const débutJson = moment(Date.now());
const objet = await response.json();
console.log(sprintf("réponse json=%j, type=%s, %s", objet, typeof (objet), heure(débutJson)));
return objet;
// se a resposta for do tipo text/plain, a resposta de texto do servidor é obtida com [response.text()]
// nesse caso, o código chamador obtém um objeto [Promise]
// [await] permite obter a resposta [texte] do servidor, em vez de sua promessa
// const text = await response.text();
// console.log("resposta de texto=", texto);
// return text;
} catch (error) {
// estamos aqui porque o servidor enviou um código de erro [404 Not Found, ...] acompanhado de um corpo vazio — exibimos o erro para verificar sua estrutura
// ou porque o cliente [fetch] lançou uma exceção (rede inacessível, ...)
// exibe-se a estrutura do erro
console.log(sprintf("error fetch en json=%j, %s", error, heure(débutFetch)));
console.log("error fetch en javascript=", typeof (error), error);
// lança-se a mensagem de erro recebida
throw error.message;
}
}
// a função main executa a função assíncrona [initSession]
async function main() {
try {
console.log("requête HTTP vers le serveur en cours ---------------------------------------------");
const response = await initSession();
console.log("succès ---------------------------------------------");
console.log("réponse=", response, typeof (response))
} catch (error) {
console.log("erreur ---------------------------------------------");
console.log("erreur=", error, typeof (error));
}
}
// teste
main();
// utilitário para exibição de hora e duração
function heure(début) {
// hora atual
const now = moment(Date.now());
// formatação da hora
let result = "heure=" + now.format("HH:mm:ss:SSS");
// é necessário calcular uma duração?
if (début) {
const durée = now - début;
const milliseconds = durée % 1000;
const seconds = Math.floor(durée / 1000);
// formatação de hora + duração
result = result + sprintf(", durée= %s seconde(s) et %s millisecondes", seconds, milliseconds);
}
// resultado
return result;
}
Comentários
- as funções HTTP do JavaScript são funções assíncronas. Aqui, aplicamos o que aprendemos na seção anterior (ver link);
- linha 24: para aguardar que a resposta da função assíncrona [fetch] seja publicada no loop de eventos de [node.js], utilizamos a palavra-chave [await]. Sabemos que essa instrução deve estar em um código prefixado pela palavra-chave [async] (linha 13);
- linhas 13-56: encapsulamos o código HTTP na função assíncrona [initSession];
- linhas 59-69: uma segunda função assíncrona [main] é usada para chamar de forma bloqueante (async/await) a função assíncrona [initSession];
- linha 72: a função assíncrona [main] é chamada;
- embora todo o código pareça síncrono, são de fato funções assíncronas que estão sendo executadas, mas de forma bloqueante;
- linha 19: para inicializar uma sessão jSON com o servidor de cálculo de impostos, é necessário enviar a ele o comando HTTP [get /main.php?action=init-session&type=json]. É isso que o código das linhas 24 a 27 faz. A sintaxe de [fetch] é a seguinte: [fetch(URL, options)] com:
- [URL]: a consulta URL;
- [options]: um objeto que define as opções da consulta. É aqui, principalmente, que se definem os cabeçalhos HTTP que se deseja enviar ao sistema de destino;
- linhas 15-18: definem-se as opções da solicitação que se deseja realizar:
- [method]: deseja-se realizar um GET;
- [timeout]: queremos que o cliente [fetch] não espere mais de 2 segundos pela resposta do servidor. Se esse prazo for excedido, [fetch] lançará uma exceção;
- linha 24: para obter o URL [/main.php?action=init-session&type=json], usa-se a biblioteca [qs] para obter a codificação URL dos parâmetros [action,type] do GET. A sequência obtida é [init-session&type=json], que poderíamos ter construído nós mesmos. Queríamos apenas mostrar como obter uma sequência URL codificada;
- linha 24: a palavra-chave [await] indica que uma tarefa assíncrona está sendo iniciada aqui e que se espera que ela publique sua resposta no loop de eventos de [node.js];
- linha 24: em [response], obtém-se um objeto complexo que descreve a resposta HTTP recebida na íntegra (cabeçalhos e documento);
- linhas 30-31: exibe-se o objeto [response] para ver sua estrutura, primeiro como uma sequência de caracteres e depois como um objeto JavaScript;
- linha 33: exibimos os cabeçalhos HTTP enviados pelo servidor;
- linha 38: sabemos que o servidor de cálculo de impostos enviará uma string jSON. Ela está encapsulada no objeto [response]. É possível obtê-la com o método [response.json()]. No entanto, esse método é assíncrono. Portanto, escrevemos [await response.json()] para obter a string jSON, que será publicada no ciclo de eventos de [node.js]. Na verdade, não é a string jSON que se obtém, mas o objeto JavaScript representado por ela;
- linha 39: exibição da string jSON recebida;
- linha 40: retorna-se o objeto JavaScript recebido;
- linha 47: intercepta-se um possível erro da instrução [fetch]. Esta só lança uma exceção se a operação HTTP não tiver sido bem-sucedida e nenhuma resposta do servidor tiver sido recebida. Se uma resposta tiver sido recebida, mesmo com um código HTTP diferente de [200 OK], [fetch] não lança uma exceção e a resposta do servidor estará disponível na linha 38;
- linhas 51-52: exibe-se o objeto [error] recebido pela cláusula [catch], primeiro como uma string jSON e, em seguida, como um objeto JavaScript;
- linha 54: a mensagem de erro de [fetch] está em [error.message];
- linhas 59-69: a função assíncrona [main] chama a função assíncrona [initSession] de forma bloqueante (await na linha 62);
- linha 72: a função assíncrona [main] é iniciada e o código principal do script é então concluído. O script global será concluído quando as tarefas assíncronas iniciadas tiverem publicado seus resultados no ciclo de eventos;
Os resultados da execução são os seguintes:
Caso 1: o servidor Laragon não está em execução
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\fetch-01.js"
requête HTTP vers le serveur en cours ---------------------------------------------
error fetch en json={"message":"network timeout at: http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json","type":"request-timeout"}, heure=10:08:48:180, durée= 2 seconde(s) et 62 millisecondes
error fetch en javascript= object { FetchError: network timeout at: http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json
at Timeout.<anonymous> (c:\Data\st-2019\dev\es6\javascript\node_modules\node-fetch\lib\index.js:1448:13)
at ontimeout (timers.js:436:11)
at tryOnTimeout (timers.js:300:5)
at listOnTimeout (timers.js:263:5)
at Timer.processTimers (timers.js:223:10)
message:
'tempo limite de rede em: http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json',
type: 'request-timeout' }
erreur ---------------------------------------------
erreur= network timeout at: http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json string
[Done] exited with code=0 in 2.804 seconds
Comentários
- linha 3: a solicitação HTTP falha após 2 segundos e 62 milissegundos devido ao tempo limite de 2 segundos que foi imposto à solicitação HTTP;
- linhas 4-9: o objeto JavaScript [error] foi interceptado pela cláusula [catch(error)]. Esse objeto possui duas propriedades:
- [FetchError]: linha 4;
- [message]: linhas 10-12;
- linha 14: a mensagem de erro recebida pela função assíncrona [main];
Caso 2: o servidor Laragon está em execução
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\fetch-01.js"
requête HTTP vers le serveur en cours ---------------------------------------------
réponse fetch formatée en json,={"size":0,"timeout":2000}, heure=10:13:50:814, durée= 0 seconde(s) et 375 millisecondes
réponse fetch en javascript= Response {
size: 0,
timeout: 2000,
[Symbol(Body internals)]:
{ body:
PassThrough {
_readableState: [ReadableState],
readable: true,
domain: null,
_events: [Object],
_eventsCount: 2,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: true,
_transformState: [Object] },
disturbed: false,
error: null },
[Symbol(Response internals)]:
{ url:
'http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json',
status: 200,
statusText: 'OK',
headers: Headers { [Symbol(map)]: [Object] },
counter: 0 } }
entêtes de la réponse= Headers {
[Symbol(map)]:
[Object: null prototype] {
date: [ 'Sat, 14 Sep 2019 08:13:50 GMT' ],
server: [ 'Apache/2.4.35 (Win64) OpenSSL/1.1.0i PHP/7.2.11' ],
'x-powered-by': [ 'PHP/7.2.11' ],
'cache-control': [ 'max-age=0, private, must-revalidate, no-cache, private' ],
'set-cookie': [ 'PHPSESSID=99q2iinusmhl55fa600aie2mmu; path=/' ],
'content-length': [ '86' ],
connection: [ 'close' ],
'content-type': [ 'application/json' ] } }
réponse json={"action":"init-session","état":700,"réponse":"session démarrée avec type [json]"}, type=object, heure=10:13:50:825, durée= 0 seconde(s) et 1 millisecondes
succès ---------------------------------------------
réponse= { action: 'init-session',
'status': 700,
'resposta': 'sessão iniciada com o tipo [json]' } objeto
[Done] exited with code=0 in 1.022 seconds
Comentários
- linha 3: [fetch] recebe a resposta do servidor após 375 ms;
- linhas 4-39: a estrutura do objeto JavaScript [response] que encapsula a resposta do servidor. Entre suas propriedades, algumas podem ser de nosso interesse:
- [status] (linha 25): código HTTP da resposta do servidor;
- [statusText] (linha 26): texto associado a esse código;
- [headers] (linha 27): os cabeçalhos HTTP da resposta do servidor;
- [body] (linha 8): representa o documento enviado pelo servidor. A instrução [fetch] oferece métodos para explorá-lo;
- linhas 29-39: os cabeçalhos HTTP da resposta do servidor;
- linha 40: a função assíncrona [response.json()] publicou sua resposta após 1 milissegundo;
- linhas 42-44: o objeto JavaScript recebido pela função assíncrona [main];
Caso 3: o servidor Laragon está em execução, mas recebemos um comando incorreto:

- acima, na linha 26, passa-se um tipo incorreto de sessão para o servidor;
Os resultados da execução são os seguintes:
requête HTTP vers le serveur en cours ---------------------------------------------
réponse fetch formatée en json,={"size":0,"timeout":2000}, heure=10:27:54:114, durée= 0 seconde(s) et 136 millisecondes
réponse fetch en javascript= Response {
size: 0,
timeout: 2000,
[Symbol(Body internals)]:
{ body:
PassThrough {
_readableState: [ReadableState],
readable: true,
domain: null,
_events: [Object],
_eventsCount: 2,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: true,
_transformState: [Object] },
disturbed: false,
error: null },
[Symbol(Response internals)]:
{ url:
'http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=x',
status: 400,
statusText: 'Bad Request',
headers: Headers { [Symbol(map)]: [Object] },
counter: 0 } }
entêtes de la réponse= Headers {
[Symbol(map)]:
[Object: null prototype] {
date: [ 'Sat, 14 Sep 2019 08:27:54 GMT' ],
server: [ 'Apache/2.4.35 (Win64) OpenSSL/1.1.0i PHP/7.2.11' ],
'x-powered-by': [ 'PHP/7.2.11' ],
'cache-control': [ 'max-age=0, private, must-revalidate, no-cache, private' ],
'set-cookie': [ 'PHPSESSID=5ku9gfok81ikj98hia0meeum57; path=/' ],
'content-length': [ '79' ],
connection: [ 'close' ],
'content-type': [ 'application/json' ] } }
réponse json={"action":"init-session","état":703,"réponse":"paramètre type=[x] invalide"}, type=object, heure=10:27:54:127, durée= 0 seconde(s) et 2 millisecondes
succès ---------------------------------------------
réponse= { action: 'init-session',
'estado': 703,
'resposta': 'parâmetro type=[x] inválido' } objeto
[Done] exited with code=0 in 0.712 seconds
- a resposta do servidor é recebida na linha 2;
- linha 24: pode-se observar que o código HTTP da resposta do servidor é 400, um código de erro. No entanto, [fetch] não lançou nenhuma exceção. Enquanto [fetch] receber uma resposta do servidor, ele a processa e não lança uma exceção;
- linhas 41-43: a resposta obtida pela função assíncrona [main];
12.4. script [fetch-02]
O script a seguir retoma o script [fetch-01], eliminando todos os detalhes desnecessários:
'use strict';
// importações
import fetch from 'node-fetch';
import qs from 'qs';
// URL base do servidor de cálculo de impostos
const baseUrl = 'http://localhost/php7/scripts-web/impostos/versão-14/main.php?';
// inicialização da sessão
async function initSession() {
// opções da consulta HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
timeout: 2000
};
// execução da consulta HTTP [get /main.php?action=init-session&type=json]
const response = await fetch(baseUrl + qs.stringify({
action: 'init-session',
type: 'json'
}), options);
// resultado recebido em jSON
return await response.json();
}
// a função main executa a função assíncrona [initSession]
async function main() {
try {
console.log("requête HTTP vers le serveur en cours ---------------------------------------------");
const response = await initSession();
console.log("succès ---------------------------------------------");
console.log("réponse=", response)
} catch (error) {
console.log("erreur ---------------------------------------------");
console.log("erreur=", error.message);
}
}
// teste
main();
Os resultados de uma execução normal:
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\fetch-02.js"
requête HTTP vers le serveur en cours ---------------------------------------------
succès ---------------------------------------------
réponse= { action: 'init-session',
'estado': 700,
'resposta': 'sessão iniciada com o tipo [json]' }
[Done] exited with code=0 in 0.56 seconds
Resultados de uma execução com exceção (o servidor Laragon é interrompido):
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\fetch-02.js"
requête HTTP vers le serveur en cours ---------------------------------------------
erreur ---------------------------------------------
erreur= network timeout at: http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json
[Done] exited with code=0 in 2.701 seconds
12.5. script [axios-01]
Retomamos aqui o script [fetch-01], que reescrevemos utilizando a biblioteca [axios]. Vale lembrar que nosso interesse por essa biblioteca é que ela seja portável entre o ambiente [node.js] e os dos navegadores comuns. Isso permite:
- na fase 1, testar nossos scripts em um ambiente [node.js];
- na fase 2, portá-los para um navegador;
O script [axios-01] retoma a estrutura do script [fetch-01]:
'use strict';
import axios from 'axios';
// configuração padrão do axios
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost/php7/scripts-web/impots/version-14';
// inicialização da sessão
async function initSession(axios) {
// opções da solicitação HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
// parâmetros da consulta URL
params: {
action: 'init-session',
type: 'json'
}
};
// execução da consulta HTTP [get /main.php?action=init-session&type=json]
try {
// solicitação assíncrona
const response = await axios.request('main.php', options);
// a resposta é o conjunto completo da resposta HTTP do servidor (cabeçalhos HTTP + a própria resposta)
// exibimos essa resposta para ver sua estrutura
console.log("réponse axios=", response);
// a resposta do servidor está em [response.data]
return response.data;
} catch (error) {
// estamos aqui porque o servidor enviou um código de erro [404 Not Found, 500 Internal Server Error, ...]
// o parâmetro [error] é uma instância de exceção — ele pode assumir diversas formas
// é exibido para que se possa ver sua estrutura
console.log("axios error=", typeof (error), error);
if (error.response) {
// o servidor sinalizou um erro no status HTTP, mas também enviou uma resposta
// portanto, esta é encontrada em [error.response.data]
// sabe-se que o servidor envia respostas jSON com a estrutura {ação, estado, resposta}
// e que, em caso de erro, a mensagem de erro está em [réponse]
return error.response.data;
} else {
// o erro é gerado
throw error;
}
}
}
// a função main executa a função assíncrona [initSession]
async function main() {
try {
console.log("requête HTTP vers le serveur en cours ---------------------------------------------");
const response = await initSession(axios);
console.log("succès ---------------------------------------------");
console.log("réponse=", response, typeof (response))
} catch (error) {
console.log("erreur ---------------------------------------------");
console.log("erreur=", error.message);
}
}
// teste
main();
Comentários
- linha 2: importamos a biblioteca [axios];
- linhas 5-6: configuração padrão das consultas HTTP. As opções [axios.defaults] são válidas para todas as consultas HTTP emitidas pelo objeto [axios], sem a necessidade de redefini-las a cada nova consulta;
- linha 5: tempo limite de 2 segundos para todas as solicitações;
- linha 6: todas as URL serão definidas em relação à URL básica;
- linha 9: a função assíncrona [initSession];
- linhas 11-18: as opções da solicitação HTTP que será emitida (além das opções padrão já definidas nas linhas 5-6);
- linhas 14-17: os parâmetros da função URL [action=init-session&type=json]. O objeto [params] será automaticamente convertido em uma cadeia de caracteres codificada URL;
- linha 22: chamada bloqueante da função assíncrona [axios.request]. O primeiro parâmetro é o URL de destino, construído a partir do [main.php] somado ao URL de base definido na linha 6. O segundo parâmetro é o objeto [options] das linhas 11 a 18;
- linha 25: [response] é um objeto JavaScript que encapsula toda a resposta HTTP do servidor (cabeçalhos HTTP + documento de resposta). Ele é exibido para que se possa ver sua estrutura em JavaScript;
- linha 27: se o servidor enviou um documento, ele é encontrado em [response.data]. Aqui sabemos que o servidor envia uma resposta jSON acompanhada do cabeçalho HTTP [Content-type : application/json]. A presença desse cabeçalho faz com que [axios] deserialize automaticamente [response.data] em um objeto JavaScript;
- linha 28: a função [axios] pode lançar uma exceção. É nesse ponto que [axios] difere de [fetch]. Uma exceção é lançada nos seguintes casos:
- a solicitação HTTP não pôde ser enviada (erro no lado do cliente);
- O servidor enviou um código de erro HTTP (400, 404, 500, …) (esse ponto, na verdade, é configurável). Vale lembrar que, se esse código de erro HTTP vier acompanhado de uma resposta, o código [fetch] não gerava uma exceção, enquanto o código [axios] gera uma. No entanto, se o código de erro HTTP for acompanhado de um documento, este é inserido em [error.response];
- linha 32: exibe-se a estrutura JavaScript do objeto [error];
- linhas 33-38: se o objeto [error] contiver um objeto [response], então é essa resposta que é devolvida ao código chamador;
- linhas 39-42: nos demais casos, o objeto [error] é retornado ao código chamador;
- linhas 47-57: a função assíncrona [main];
- linha 50: chamada bloqueante à função assíncrona [initSession]. Recupera-se a resposta jSON do servidor como um objeto JavaScript;
- linhas 53-56: interceptação de um eventual erro. A mensagem de erro está em [error.message];
Os resultados da execução são os seguintes:
Caso 1: o servidor Laragon não está em execução
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\axios-01.js"
requête HTTP vers le serveur en cours ---------------------------------------------
axios error= object { Error: timeout of 2000ms exceeded
at createError (c:\Data\st-2019\dev\es6\javascript\node_modules\axios\lib\core\createError.js:16:15)
at Timeout.handleRequestTimeout (c:\Data\st-2019\dev\es6\javascript\node_modules\axios\lib\adapters\http.js:252:16)
at ontimeout (timers.js:436:11)
at tryOnTimeout (timers.js:300:5)
at listOnTimeout (timers.js:263:5)
at Timer.processTimers (timers.js:223:10)
config:
{ url:
'http://localhost/php7/scripts-web/impots/version-14/main.php',
method: 'get',
params: { action: 'init-session', type: 'json' },
headers:
{ Accept: 'application/json, text/plain, */*',
'User-Agent': 'axios/0.19.0' },
baseURL: 'http://localhost/php7/scripts-web/impots/version-14',
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 2000,
adapter: [Function: httpAdapter],
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
data: undefined },
code: 'ECONNABORTED',
request:
Writable {
_writableState:
WritableState {
objectMode: false,
highWaterMark: 16384,
finalCalled: false,
needDrain: false,
ending: false,
ended: false,
finished: false,
destroyed: false,
decodeStrings: true,
defaultEncoding: 'utf8',
length: 0,
writing: false,
corked: 0,
sync: true,
bufferProcessing: false,
onwrite: [Function: bound onwrite],
writecb: null,
writelen: 0,
bufferedRequest: null,
lastBufferedRequest: null,
pendingcb: 0,
prefinished: false,
errorEmitted: false,
emitClose: true,
bufferedRequestCount: 0,
corkedRequestsFree: [Object] },
writable: true,
domain: null,
_events:
[Object: null prototype] {
response: [Function: handleResponse],
error: [Function: handleRequestError] },
_eventsCount: 2,
_maxListeners: undefined,
_options:
{ protocol: 'http:',
maxRedirects: 21,
maxBodyLength: 10485760,
path:
'/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json',
method: 'GET',
headers: [Object],
agent: undefined,
auth: undefined,
hostname: 'localhost',
port: null,
nativeProtocols: [Object],
pathname: '/php7/scripts-web/impots/version-14/main.php',
search: '?action=init-session&type=json' },
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 0,
_requestBodyBuffers: [],
_onNativeResponse: [Function],
_currentRequest:
ClientRequest {
domain: null,
_events: [Object],
_eventsCount: 6,
_maxListeners: undefined,
output: [],
outputEncodings: [],
outputCallbacks: [],
outputSize: 0,
writable: true,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
useChunkedEncodingByDefault: false,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: 0,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: [Socket],
connection: [Socket],
_header:
'GET /php7/scripts-web/impostos/versão-14/main.php?action=init-session&type=json HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nUser-Agent: axios/0.19.0\r\nHost: localhost\r\nConnection: close\r\n\r\n',
_onPendingData: [Function: noopPendingOutput],
agent: [Agent],
socketPath: undefined,
timeout: undefined,
method: 'GET',
path:
'/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json',
_ended: false,
res: null,
aborted: 1568528450762,
timeoutCb: null,
upgradeOrConnect: false,
parser: [HTTPParser],
maxHeadersCount: null,
_redirectable: [Circular],
[Symbol(isCorked)]: false,
[Symbol(outHeadersKey)]: [Object] },
_currentUrl:
'http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json' },
response: undefined,
isAxiosError: true,
toJSON: [Function] }
erreur ---------------------------------------------
erreur= timeout of 2000ms exceeded
[Done] exited with code=0 in 2.784 seconds
Comentários
- linhas 33-136: o objeto [error] contém diversas informações;
- [Error], linhas 3-9: uma descrição do erro que ocorreu;
- [config], linhas 10-27: a configuração da consulta HTTP que levou a esse erro;
- [config.url], linhas 11-12: o destino URL;
- [config.method], linha 13: método da consulta;
- [config.params], linha 14: os parâmetros de URL;
- [config.headers], linhas 16-17: os cabeçalhos HTTP da consulta;
- [config.baseURL], linha 18: o URL de base do URL de destino;
- [config.timeout], linha 21: o tempo limite da solicitação;
- [code], linha 28: um código de erro;
- [request], linhas 29-133: uma descrição detalhada da solicitação HTTP. Observe-se que a maioria das propriedades é precedida pelo sublinhado _, indicando que se trata de propriedades internas do objeto [request], não destinadas a serem utilizadas diretamente pelo desenvolvedor;
- [response], linha 134: a resposta do servidor, neste caso inexistente;
- linha 138: a mensagem de erro exibida pela função [main];
Caso 2: o servidor Laragon está em execução
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\axios-01.js"
requête HTTP vers le serveur en cours ---------------------------------------------
réponse axios= { status: 200,
statusText: 'OK',
headers:
{ date: 'Sun, 15 Sep 2019 07:09:26 GMT',
server: 'Apache/2.4.35 (Win64) OpenSSL/1.1.0i PHP/7.2.11',
'x-powered-by': 'PHP/7.2.11',
'cache-control': 'max-age=0, private, must-revalidate, no-cache, private',
'set-cookie': [ 'PHPSESSID=uas6lugtblstktcifpd8e5irm6; path=/' ],
'content-length': '86',
connection: 'close',
'content-type': 'application/json' },
config:
{ url:
'`http://localhost/php7/scripts-web/impots/version-14/main.php'`,
method: 'get',
params: { action: 'init-session', type: 'json' },
headers:
{ Accept: 'application/json, text/plain, */*',
''User-Agent': 'axios/0.19.0' },
baseURL: 'http://localhost/php7/scripts-web/impots/version-14',
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 2000,
adapter: [Function: httpAdapter],
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
data: undefined },
request:
ClientRequest {
domain: null,
_events:
[Object: null prototype] {
socket: [Function],
abort: [Function],
aborted: [Function],
error: [Function],
timeout: [Function],
prefinish: [Function: requestOnPrefinish] },
_eventsCount: 6,
_maxListeners: undefined,
output: [],
outputEncodings: [],
outputCallbacks: [],
outputSize: 0,
writable: true,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
useChunkedEncodingByDefault: false,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: 0,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket:
Socket {
connecting: false,
_hadError: false,
_handle: [TCP],
_parent: null,
_host: 'localhost',
_readableState: [ReadableState],
readable: true,
domain: null,
_events: [Object],
_eventsCount: 7,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: null,
_server: null,
parser: null,
_httpMessage: [Circular],
[Symbol(asyncId)]: 6,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0 },
connection:
Socket {
connecting: false,
_hadError: false,
_handle: [TCP],
_parent: null,
_host: 'localhost',
_readableState: [ReadableState],
readable: true,
domain: null,
_events: [Object],
_eventsCount: 7,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: null,
_server: null,
parser: null,
_httpMessage: [Circular],
[Symbol(asyncId)]: 6,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0 },
_header:
'GET /php7/scripts-web/impots/version-14/main.php?action=init-session&type=json HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nUser-Agent: axios/0.19.0\r\nHost: localhost\r\nConnection: close\r\n\r\n',
_onPendingData: [Function: noopPendingOutput],
agent:
Agent {
domain: null,
_events: [Object],
_eventsCount: 1,
_maxListeners: undefined,
defaultPort: 80,
protocol: 'http:',
options: [Object],
requests: {},
sockets: [Object],
freeSockets: {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256 },
socketPath: undefined,
timeout: undefined,
method: 'GET',
path:
'/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json',
_ended: true,
res:
IncomingMessage {
_readableState: [ReadableState],
readable: false,
domain: null,
_events: [Object],
_eventsCount: 3,
_maxListeners: undefined,
socket: [Socket],
connection: [Socket],
httpVersionMajor: 1,
httpVersionMinor: 0,
httpVersion: '1.0',
complete: true,
headers: [Object],
rawHeaders: [Array],
trailers: {},
rawTrailers: [],
aborted: false,
upgrade: false,
url: '',
method: null,
statusCode: 200,
statusMessage: 'OK',
client: [Socket],
_consuming: false,
_dumped: false,
req: [Circular],
responseUrl:
'http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json',
redirects: [] },
aborted: undefined,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
_redirectable:
Writable {
_writableState: [WritableState],
writable: true,
domain: null,
_events: [Object],
_eventsCount: 2,
_maxListeners: undefined,
_options: [Object],
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 0,
_requestBodyBuffers: [],
_onNativeResponse: [Function],
_currentRequest: [Circular],
_currentUrl:
'http://localhost/php7/scripts-web/impots/version-14/main.php?action=init-session&type=json' },
[Symbol(isCorked)]: false,
[Symbol(outHeadersKey)]:
[Object: null prototype] { accept: [Array], 'user-agent': [Array], host: [Array] } },
data:
{ action: 'init-session',
'estado': 700,
'resposta': 'sessão iniciada com o tipo [json]' } }
succès ---------------------------------------------
réponse= { action: 'init-session',
'estado': 700,
'resposta': 'sessão iniciada com o tipo [json]' } objeto
[Done] exited with code=0 in 1.115 seconds
Comentários
- linhas 3-203: o objeto JavaScript [response] que encapsula a resposta HTTP do servidor;
- linha 3, [status]: o código HTTP da resposta;
- linha 4, [statusText]: o texto associado ao código HTTP anterior;
- linhas 5-13, [headers]: os cabeçalhos HTTP da resposta:
- linha 10, [Set-Cookie]: o cookie de sessão;
- linha 13, [Content-Type]: o tipo do documento enviado pelo servidor;
- linhas 14-31, [config]: a configuração da solicitação HTTP enviada;
- linhas 32-199, [request]: o objeto JavaScript que detalha a solicitação HTTP enviada;
- linhas 200-203, [request.data]: o objeto JavaScript que encapsula a resposta jSON do servidor;
- linhas 205-207: a resposta recuperada pela função assíncrona [main];
Caso 3: é feita uma solicitação incorreta [init-session] ao servidor Laragon;

Os resultados da execução são os seguintes:
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\axios-01.js"
requête HTTP vers le serveur en cours ---------------------------------------------
axios error= object { Error: Request failed with status code 400
...
config:
{ url:
'http://localhost/php7/scripts-web/impots/version-14/main.php',
...
data: undefined },
request:
...
[Symbol(outHeadersKey)]:
[Object: null prototype] { accept: [Array], 'user-agent': [Array], host: [Array] } },
response:
{ status: 400,
statusText: 'Bad Request',
headers:
{ date: 'Sun, 15 Sep 2019 07:25:58 GMT',
server: 'Apache/2.4.35 (Win64) OpenSSL/1.1.0i PHP/7.2.11',
'x-powered-by': 'PHP/7.2.11',
'cache-control': 'max-age=0, private, must-revalidate, no-cache, private',
'set-cookie': [Array],
'content-length': '79',
connection: 'close',
'content-type': 'application/json' },
config:
{ url:
'`http://localhost/php7/scripts-web/impots/version-14/main.php'',
...
data: undefined },
request:
...
[Symbol(outHeadersKey)]: [Object] },
data:
{ action: 'init-session',
''status': 703,
'resposta': 'parâmetro type=[x] inválido' } },
isAxiosError: true,
toJSON: [Function] }
succès ---------------------------------------------
réponse= { action: 'init-session',
'estado': 703,
'resposta': 'parâmetro type=[x] inválido' } objeto
[Done] exited with code=0 in 0.69 seconds
Como o servidor respondeu com o código HTTP 400 (linha 15), o [axios] lançou uma exceção (mais uma vez, esse comportamento é configurável). Embora o [axios] tenha lançado uma exceção, recebemos a resposta HTTP do servidor em [error.response] (linha 14) e o documento jSON enviado por [error.response.data] (linha 34). Linhas 41-43: a função [main] recupera corretamente a resposta jSON do servidor.
12.6. script [axios-02]
Agora que detalhamos os objetos manipulados pela biblioteca [axios] durante uma solicitação HTTP, podemos reescrever o script [axios-01] da seguinte maneira:
'use strict';
import axios from 'axios';
// configuração padrão do axios
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost/php7/scripts-web/impots/versão-14';
// inicialização da sessão
async function initSession(axios) {
// opções da solicitação HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
// parâmetros da consulta URL
params: {
action: 'init-session',
type: 'json'
}
};
try {
// execução da consulta HTTP [get /main.php?action=init-session&type=json]
const response = await axios.request('main.php', options);
// a resposta do servidor está em [response.data]
return response.data;
} catch (error) {
// resposta do servidor
if (error.response) {
// a resposta jSON está em [error.response.data]
return error.response.data;
} else {
// o erro é reenviado
throw error;
}
}
}
// a função main executa a função assíncrona [initSession]
async function main() {
try {
console.log("requête HTTP vers le serveur en cours ---------------------------------------------");
const response = await initSession(axios);
console.log("succès ---------------------------------------------");
console.log("réponse=", response, typeof (response))
} catch (error) {
console.log("erreur ---------------------------------------------");
console.log("erreur=", error.message);
}
}
// teste
main();
12.7. script [axios-03]
O script [axios-03] segue a metodologia do script [axios-02]. Desta vez, adiciona-se a solicitação HTTP [authentifier-utilisateur] ao servidor, o que é feito por meio de um POST:
'use strict';
import axios from 'axios';
import qs from 'qs'
// configuração do Axios
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost/php7/scripts-web/impots/versão-14';
// inicialização da sessão
async function initSession(axios) {
// opções da solicitação HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
// parâmetros da consulta URL
params: {
action: 'init-session',
type: 'json'
}
};
try {
// execução da consulta HTTP [get /main.php?action=init-session&type=json]
const response = await axios.request('main.php', options);
// a resposta do servidor está em [response.data]
return response.data;
} catch (error) {
// resposta do servidor
if (error.response) {
// a resposta jSON está em [error.response.data]
return error.response.data;
} else {
// o erro é reenviado
throw error;
}
}
}
async function authentifierUtilisateur(axios, user, password) {
// opções da solicitação HHTP [POST /main.php?action=authentifier-utilisateur]
const options = {
method: "POST",
headers: {
'Content-type': 'application/x-www-form-urlencoded',
},
// corpo do POST
data: qs.stringify({
user: user,
password: password
}),
// parâmetros do URL
params: {
action: 'authentifier-utilisateur'
}
};
try {
// execução da solicitação HTTP [post /main.php?action=authentifier-utilisateur]
const response = await axios.request('main.php', options);
// a resposta do servidor está em [response.data]
return response.data;
} catch (error) {
// resposta do servidor
if (error.response) {
// a resposta jSON está em [error.response.data]
return error.response.data;
} else {
// o erro é reenviado
throw error;
}
}
}
// a função main executa as funções assíncronas uma a uma
async function main() {
try {
// init-session
console.log("action init-session en cours ---------------------------------------------");
const response1 = await initSession(axios);
console.log("succès ---------------------------------------------");
console.log("réponse=", response1);
// autenticar-usuário
console.log("action authentifier-utilisateur en cours ---------------------------------------------");
const response2 = await authentifierUtilisateur(axios, 'admin', 'admin');
console.log("succès ---------------------------------------------");
console.log("réponse=", response2)
} catch (error) {
console.log("erreur ---------------------------------------------");
console.log("erreur=", error);
}
}
// teste
main();
Comentários
- linhas 38-70: a função assíncrona [authentifierUtilisateur];
- linha 39: é necessário executar a consulta [POST /main.php?action=authentifier-utilisateur];
- linhas 40-54: as opções da consulta HTTP;
- linha 41: trata-se de um POST;
- linhas 42-44: os parâmetros do POST serão codificados como URL em um documento que o cliente envia junto com sua solicitação;
- linhas 46-49: a propriedade [data] deve conter a string codificada de POST URL. Para isso, utiliza-se aqui a biblioteca [qs] importada na linha 3;
- linhas 55-69: para a execução da consulta, encontramos o mesmo código que no método [initSession];
- linhas 73-89: o método [asynchrone] chama sucessivamente, de forma bloqueante, os métodos [initSession, authentifierUtilisateur], nas linhas 77 e 82;
- linha 82: utiliza-se o par (admin, admin) como credenciais de conexão. Sabe-se que elas são reconhecidas pelo servidor;
Os resultados da execução são os seguintes:
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\axios-03.js"
action init-session en cours ---------------------------------------------
succès ---------------------------------------------
réponse= { action: 'init-session',
''status': 700,
'resposta': 'sessão iniciada com o tipo [json]' }
action authentifier-utilisateur en cours ---------------------------------------------
succès ---------------------------------------------
réponse= { action: 'authentifier-utilisateur',
'estado': 103,
'resposta':
[ 'pas de session en cours. Commencer par action [init-session]' ] }
[Done] exited with code=0 in 0.834 seconds
- linhas 9-12: a autenticação do usuário falha: o servidor não registrou o fato de que havíamos iniciado uma sessão jSON. Isso ocorre porque não foi reenviado o cookie de sessão enviado em resposta à primeira solicitação [init-session];
12.8. script [axios-04]
O script [axios-04] traz duas melhorias em relação ao script [axios-03]:
- ele gerencia o cookie de sessão;
- ele agrupa em uma função [getRemoteData] o que é comum às funções [initSession] e [authentifierUtilisateur];
'use strict';
import axios from 'axios';
import qs from 'qs'
// configuração do Axios
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost/php7/scripts-web/impots/versão-14';
// cookie de sessão
const sessionCookieName = "PHPSESSID";
let sessionCookie = '';
// inicialização da sessão
async function initSession(axios) {
// opções da solicitação HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
// parâmetros da consulta URL
params: {
action: 'init-session',
type: 'json'
}
};
// execução da consulta HTTP
return await getRemoteData(axios, options);
}
async function authentifierUtilisateur(axios, user, password) {
// opções da consulta HHTP [post /main.php?action=authentifier-utilisateur]
const options = {
method: "POST",
headers: {
'Content-type': 'application/x-www-form-urlencoded',
},
// corpo do POST
data: qs.stringify({
user: user,
password: password
}),
// parâmetros do URL
params: {
action: 'authentifier-utilisateur'
}
};
// execução da solicitação HTTP
return await getRemoteData(axios, options);
}
async function getRemoteData(axios, options) {
// para o cookie de sessão
if (!options.headers) {
options.headers = {};
}
options.headers.Cookie = sessionCookie;
// execução da solicitação HTTP
let response;
try {
// solicitação assíncrona
response = await axios.request('main.php', options);
} catch (error) {
// o parâmetro [error] é uma instância de exceção — pode assumir diversas formas
if (error.response) {
// a resposta do servidor está em [error.response]
response = error.response;
} else {
// o erro é reenviado
throw error;
}
}
// a resposta é o conjunto completo da resposta HTTP do servidor (cabeçalhos HTTP + a própria resposta)
// recupera-se o cookie de sessão, caso exista
const setCookie = response.headers['set-cookie'];
if (setCookie) {
// setCookie é uma matriz
// procura-se o cookie de sessão nessa matriz
let trouvé = false;
let i = 0;
while (!trouvé && i < setCookie.length) {
// procura-se o cookie de sessão
const results = RegExp('^(' + sessionCookieName + '.+?);').exec(setCookie[i]);
if (results) {
// armazenamos o cookie de sessão
// eslint-disable-next-line require-atomic-updates
sessionCookie = results[1];
// encontrado
trouvé = true;
} else {
// próximo elemento
i++;
}
}
}
// a resposta do servidor está em [response.data]
return response.data;
}
// a função main executa as funções assíncronas uma a uma
async function main() {
try {
// init-session
console.log("action init-session en cours ---------------------------------------------");
const response1 = await initSession(axios);
console.log("succès ---------------------------------------------");
console.log("réponse=", response1);
// autenticar-usuário
console.log("action authentifier-utilisateur en cours ---------------------------------------------");
const response2 = await authentifierUtilisateur(axios, 'admin', 'admin');
console.log("succès ---------------------------------------------");
console.log("réponse=", response2)
} catch (error) {
console.log("erreur ---------------------------------------------");
console.log("erreur=", error.message);
}
}
// teste
main();
Comentários
- linhas 14-26: a função [initSession]. Agora, ela se limita a preparar a consulta HTTP a ser enviada ao servidor, mas não a executa. Ela delega essa função ao método [getRemoteDate], nas linhas 49-95;
- linhas 28-47: a função [authentifierUtilisateur] segue o mesmo procedimento;
- linha 49: a função [getRemoteData] recebe as duas informações que lhe permitem executar uma solicitação HTTP:
- [axios], o objeto responsável por enviar a consulta e receber a resposta;
- [options], as opções de configuração da consulta a ser enviada ao servidor;
- linha 59: execução da consulta e espera bloqueante pela resposta jSON;
- linhas 60-68: tratamento de uma eventual exceção;
- linha 64: recupera-se a resposta, que pode estar encapsulada no objeto de erro;
- linha 67: se o servidor tiver lançado uma exceção sem incluir a resposta do servidor, então o erro recebido é repassado ao código chamador;
- a função [getRemoteData] gerencia o cookie de sessão:
- ele o armazena na variável [sessionCookie] (linha 11) ao recebê-lo pela primeira vez;
- em seguida, ele o reenvia a cada nova solicitação HTTP;
- linhas 72-92: [getRemoteData] analisa cada resposta do servidor para verificar se ele enviou o cabeçalho HTTP [Set-Cookie]. Sabemos que o servidor envia um cookie de sessão chamado [PHPSESSID] (linha 10). Portanto, é esse cookie que estamos procurando (linha 10);
- linha 72: recuperamos os cabeçalhos HTTP e [Set-Cookie], caso existam (não importa se as letras estão em maiúsculas ou minúsculas). De fato, pode haver vários cabeçalhos [Set-Cookie] e, portanto, recuperamos um array;
- linha 73: se tiver sido recuperada uma matriz de cookies;
- linhas 78-90: procura-se o cookie de sessão entre todos os cookies da matriz;
- linha 80: a expressão relacional que permite procurar o cookie de sessão no cookie nº i;
- linha 81: se a comparação retornou resultados;
- linha 84: temos em results[1] o primeiro parêntese do modelo da expressão relacional, ou seja, (PHPSESSID=xxxx) até o ponto final (não incluído) que encerra o cookie de sessão;
- linhas 50-54: a cada solicitação, o cookie de sessão é incluído nos cabeçalhos HTTP da solicitação. Na primeira vez, esse cookie está vazio e, portanto, será ignorado pelo servidor;
Os resultados da execução são os seguintes:
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\http\axios-04.js"
action init-session en cours ---------------------------------------------
succès ---------------------------------------------
réponse= { action: 'init-session',
'estado': 700,
'resposta': 'sessão iniciada com o tipo [json]' }
action authentifier-utilisateur en cours ---------------------------------------------
succès ---------------------------------------------
réponse= { action: 'authentifier-utilisateur',
'estado': 200,
'resposta': 'Autenticação bem-sucedida [admin, admin]' }
[Done] exited with code=0 in 0.982 seconds