12. Funções HTTP do JavaScript

12.1. Escolher uma biblioteca HTTP
Escolhemos duas bibliotecas aqui:
O ECMAScript 6 possui nativamente uma função HTTP chamada [fetch] que não está implementada no [node.js] (em setembro de 2019). Existe uma biblioteca chamada [node-fetch] que permite utilizar a função [fetch] no Node. Esta biblioteca utiliza determinadas APIs específicas do [node.js]. O código [node-fetch] pode, portanto, não ser 100% portátil para um ambiente que não seja [node], como um navegador;
Existe também uma biblioteca chamada [axios] dedicada a pedidos HTTP que é compatível tanto com [node.js] como com navegadores. Esta é a biblioteca que acabaremos por utilizar.
Apresentaremos o mesmo script escrito utilizando ambas as bibliotecas para demonstrar que a abordagem de codificação é semelhante.
12.2. Configurar um ambiente de desenvolvimento
12.2.1. Instalação do servidor de cálculo de impostos
Por fim, iremos escrever uma aplicação web com a seguinte arquitetura:

JS: JavaScript
O código JavaScript é do lado do cliente:
- de um serviço que fornece páginas ou fragmentos estáticos;
- um serviço JSON;
O código JavaScript é, portanto, um cliente JSON e, como tal, pode ser organizado em camadas [UI, lógica de negócio, DAO] (UI: Interface do Utilizador), tal como os nossos clientes JSON escritos em PHP.
O servidor será o servidor de cálculo de impostos para o qual já escrevemos 13 versões. Vamos escrever uma 14.ª. Começamos, portanto, por duplicar, no NetBeans, a pasta da versão 13 para a pasta da versão 14:

- em [6], modificamos o ficheiro [config.json] da versão 14 da seguinte forma:
{
"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 o diretório raiz da aplicação;
Para aceder a este servidor, deve iniciar os serviços [Laragon].
Depois de fazer isto, podemos testar esta nova versão do servidor — que, neste momento, é idêntica à versão 13 — utilizando o [Postman] (ver artigo em link). Podemos utilizar o conjunto de pedidos usado para testar a versão 12 do servidor de cálculo de impostos:

- em [1-4], utilize a solicitação [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;
- após a execução, devemos receber a resposta JSON [6] do servidor;
A versão 14 do servidor está agora operacional. Teremos de a modificar ligeiramente. Vamos rever a API deste servidor:
Ação | Função | Contexto de execução |
init-session | Utilizado para definir o tipo (json, xml, html) das respostas pretendidas | Pedido GET main.php?action=init-session&type=x pode ser enviada a qualquer momento |
authenticate-user | Autoriza ou recusa o login de um utilizador | Pedido POST main.php?action=authenticate-user A solicitação deve conter dois parâmetros postados [user, password] Só pode ser emitida se o tipo de sessão (json, xml, html) for conhecido |
calculate-tax | Realiza uma simulação de cálculo de impostos | Pedido POST para main.php?action=calculate-tax A solicitação deve conter três parâmetros enviados [casado, filhos, salário] Só pode ser emitida se o tipo de sessão (json, xml, html) for conhecido e o utilizador estiver autenticado |
list-simulations | Pedido para visualizar a lista de simulações realizadas desde o início da sessão | Pedido GET main.php?action=list-simulations A solicitação não aceita nenhum outro parâmetro Só pode ser emitida se o tipo de sessão (json, xml, html) for conhecido e o utilizador estiver autenticado |
delete-simulation | Elimina uma simulação da lista de simulações | Pedido GET main.php?action=list-simulations&number=x A solicitação não aceita nenhum outro parâmetro Só pode ser emitida se o tipo de sessão (json, xml, html) for conhecido e o utilizador estiver autenticado |
end-session | Encerra a sessão de simulação. | Tecnicamente, a sessão web antiga é eliminada e é criada uma nova sessão Só pode ser emitida se o tipo de sessão (json, xml, html) for conhecido e o utilizador estiver autenticado |
12.2.2. Instalação das bibliotecas HTTP do cliente JavaScript
Inicialmente, trabalharemos com a seguinte arquitetura:

- Em [1], um script de consola [node.js] faz uma solicitação HTTP ao servidor JSON de cálculo de impostos;
- Em [4], recebe essa resposta e apresenta-a na consola;
No Exemplo 1, utilizaremos as bibliotecas [node-fetch] e [axios] e, posteriormente, manteremos apenas a [axios] para os exemplos seguintes. Iremos agora instalar estas duas bibliotecas JavaScript a partir do terminal do [VSCode]:

Iremos também utilizar a biblioteca [qs], que permite a codificação de uma string para URL. Recorde-se que esta codificação é utilizada para codificar os parâmetros de um pedido 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. O seu código é o seguinte:
'use strict';
// imports
import fetch from 'node-fetch';
import qs from 'qs';
import { sprintf } from 'sprintf-js';
import moment from 'moment';
// URL base of tax calculation server
const baseUrl = 'http://localhost/php7/scripts-web/impots/version-14/main.php?';
// init session
async function initSession() {
// query options HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
timeout: 2000
};
// execute query HTTP [get /main.php?action=init-session&type=json]
let débutFetch;
try {
// asynchronous request - [fetch] makes a promise
débutFetch = moment(Date.now());
const response = await fetch(baseUrl + qs.stringify({
action: 'init-session',
type: 'json'
}), options);
// [response] is the entire HTTP response from the server (HTTP headers + response itself)
// display this answer to see its structure
console.log(sprintf("réponse fetch formatée en json,=%j, %s", response, heure(débutFetch)));
console.log("réponse fetch en javascript=", response);
// you can have HTTP headers
console.log("entêtes de la réponse=", response.headers);
// if application/json response, the server's json response is obtained with the asynchronous function [response.json()]
// in which case the calling code obtains a [Promise] object
// [await] allows you to obtain the server's [json] response rather than its promise
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;
// if text / plain, the text response from the server is obtained with [response.text()]
// in which case the calling code obtains a [Promise] object
// [await] allows you to obtain the server's [text] response rather than its promise
// const text = await response.text();
// console.log("answer text=", text);
// return text;
} catch (error) {
// we're here because the server has sent an error code [404 Not Found, ...] accompanied by an empty body - we display the error to see its structure
// or because the [fetch] client has thrown an exception (network inaccessible, ...)
// the error structure is displayed
console.log(sprintf("error fetch en json=%j, %s", error, heure(débutFetch)));
console.log("error fetch en javascript=", typeof (error), error);
// launch the error message received
throw error.message;
}
}
// the main function executes the asynchronous function [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));
}
}
// test
main();
// time and duration display utility
function heure(début) {
// current time
const now = moment(Date.now());
// time formatting
let result = "heure=" + now.format("HH:mm:ss:SSS");
// is it necessary to calculate a duration?
if (début) {
const durée = now - début;
const milliseconds = durée % 1000;
const seconds = Math.floor(durée / 1000);
// format time + duration
result = result + sprintf(", durée= %s seconde(s) et %s millisecondes", seconds, milliseconds);
}
// result
return result;
}
Comentários
- As funções HTTP do JavaScript são funções assíncronas. Aqui, estamos a aplicar o que aprendemos na secção anterior (ver link);
- linha 24: para aguardar que a resposta da função assíncrona [fetch] seja publicada no ciclo de eventos [node.js], usamos a palavra-chave [await]. Sabemos que esta instrução deve estar dentro de código precedido pela palavra-chave [async] (linha 13);
- linhas 13–56: encapsulamos o código HTTP dentro da função assíncrona [initSession];
- linhas 59–69: uma segunda função assíncrona [main] é utilizada para chamar a função assíncrona [initSession] de forma bloqueante (async/await);
- linha 72: a função assíncrona [main] é chamada;
- embora todo o código se assemelhe a código síncrono, estas são, de facto, funções assíncronas que são executadas, mas de forma bloqueante;
- linha 19: para inicializar uma sessão JSON com o servidor de cálculo de impostos, deve enviar-lhe o pedido HTTP [get /main.php?action=init-session&type=json]. É isto que o código nas linhas 24–27 faz. A sintaxe para [fetch] é a seguinte: [fetch(URL, options)] com:
- [URL]: a URL que está a ser consultada;
- [options]: um objeto que define as opções da solicitação. É aqui que definimos os cabeçalhos HTTP que queremos enviar ao servidor de destino;
- linhas 15–18: definimos as opções para a solicitação que queremos fazer:
- [method]: queremos realizar um GET;
- [timeout]: queremos que o cliente [fetch] espere no máximo 2 segundos pela resposta do servidor. Se este tempo limite for excedido, [fetch] lançará uma exceção;
- linha 24: para obter a URL [/main.php?action=init-session&type=json], usamos a biblioteca [qs] para obter os parâmetros codificados na URL [action,type] da solicitação GET. A string resultante é [init-session&type=json], que poderíamos ter construído nós mesmos. Queríamos simplesmente demonstrar como obter uma string codificada na URL;
- linha 24: a palavra-chave [await] indica que uma tarefa assíncrona está a ser iniciada aqui e que estamos à espera que ela publique a sua resposta no ciclo de eventos [node.js];
- linha 24: em [response], obtemos um objeto complexo que descreve toda a resposta HTTP recebida (cabeçalhos e corpo);
- linhas 30–31: Imprimimos o objeto [response] para ver a sua estrutura, primeiro como uma string 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. Esta string está encapsulada no objeto [response]. Podemos recuperá-la utilizando o método [response.json()]. No entanto, este método é assíncrono. Por isso, escrevemos [await response.json()] para recuperar a string JSON que será publicada no ciclo de eventos [node.js]. Na verdade, não é a string JSON em si que obtemos, mas o objeto JavaScript por ela representado;
- linha 39: exibição da string JSON recebida;
- linha 40: devolve o objeto JavaScript recebido;
- linha 47: capturamos quaisquer erros potenciais da instrução [fetch]. Esta instrução apenas lança uma exceção se a operação HTTP falhar e não for recebida qualquer resposta do servidor. Se for recebida uma resposta, mesmo com um código de estado 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: o objeto [error] recebido pela cláusula [catch] é exibido, primeiro como uma string JSON e depois como um objeto JavaScript;
- linha 54: a mensagem de erro de [fetch] é armazenada 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 do script principal fica então concluído. O script completo terminará quando as tarefas assíncronas iniciadas tiverem publicado os 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:
'network timeout at: 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: o pedido HTTP falha após 2 segundos e 62 milissegundos devido ao tempo limite de 2 segundos imposto ao pedido HTTP;
- linhas 4–9: o objeto JavaScript [error] interceptado pela cláusula [catch(error)]. Este objeto tem 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',
'état': 700,
'réponse': 'session démarrée avec type [json]' } object
[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 as suas propriedades, algumas podem ser do nosso interesse:
- [status] (linha 25): código de estado HTTP da resposta do servidor;
- [statusText] (linha 26): texto associado a este 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] fornece métodos para trabalhar com ele;
- linhas 29–39: os cabeçalhos HTTP da resposta do servidor;
- linha 40: a função assíncrona [response.json()] devolveu a sua resposta após 1 milésimo de segundo;
- linhas 42–44: o objeto JavaScript recebido pela função assíncrona [main];
Caso 3: O servidor Laragon está em execução, mas é-lhe enviado um comando incorreto:

- acima, na linha 26, é passado um tipo de sessão incorreto 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',
'état': 703,
'réponse': 'paramètre type=[x] invalide' } object
[Done] exited with code=0 in 0.712 seconds
- A resposta do servidor é recebida na linha 2;
- linha 24: podemos ver que o código de estado HTTP da resposta do servidor é 400, um código de erro. No entanto, [fetch] não lançou uma exceção. Desde que [fetch] receba uma resposta do servidor, processa-a 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 reutiliza o script [fetch-01], eliminando todos os detalhes desnecessários:
'use strict';
// imports
import fetch from 'node-fetch';
import qs from 'qs';
// URL base of tax calculation server
const baseUrl = 'http://localhost/php7/scripts-web/impots/version-14/main.php?';
// init session
async function initSession() {
// query options HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
timeout: 2000
};
// execute query HTTP [get /main.php?action=init-session&type=json]
const response = await fetch(baseUrl + qs.stringify({
action: 'init-session',
type: 'json'
}), options);
// result received in jSON
return await response.json();
}
// the main function executes the asynchronous function [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);
}
}
// test
main();
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',
'état': 700,
'réponse': 'session démarrée avec type [json]' }
[Done] exited with code=0 in 0.56 seconds
Resultados de uma execução com uma exceção (parando o servidor Laragon):
[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]
Aqui, retomamos o script [fetch-01], que reescrevemos utilizando a biblioteca [axios]. Recorde-se que o nosso interesse nesta biblioteca reside na sua portabilidade entre o ambiente [node.js] e os navegadores comuns. Isto permite:
- Na Fase 1, testar os nossos scripts num ambiente [Node.js];
- na fase 2, portá-los para um navegador;
O script [axios-01] segue a estrutura do script [fetch-01]:
'use strict';
import axios from 'axios';
// axios default configuration
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost/php7/scripts-web/impots/version-14';
// init session
async function initSession(axios) {
// query options HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
// URL parameters
params: {
action: 'init-session',
type: 'json'
}
};
// execute query HTTP [get /main.php?action=init-session&type=json]
try {
// asynchronous request
const response = await axios.request('main.php', options);
// response is the entire HTTP response from the server (HTTP headers + response itself)
// display this answer to see its structure
console.log("réponse axios=", response);
// the server response is in [response.data]
return response.data;
} catch (error) {
// we're here because the server has sent an error code [404 Not Found, 500 Internal Server Error, ...]
// the [error] parameter is an exception instance - it can take various forms
// display it to see its structure
console.log("axios error=", typeof (error), error);
if (error.response) {
// the server reported an error in status HTTP but also sent a response
// then it is found in [error.response.data]
// we know that the server sends jSON responses with structure {action, status, response}
// and that in the event of an error, the error msg is in [reply]
return error.response.data;
} else {
// we launch the error
throw error;
}
}
}
// the main function executes the asynchronous function [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);
}
}
// test
main();
Comentários
- linha 2: importamos a biblioteca [axios];
- linhas 5-6: configuração padrão para pedidos HTTP. As opções [axios.defaults] aplicam-se a todos os pedidos HTTP enviados pelo objeto [axios] sem necessidade de serem especificadas para cada novo pedido;
- linha 5: tempo limite de 2 segundos para todas as solicitações;
- linha 6: todas as URLs serão relativas à URL base;
- linha 9: a função assíncrona [initSession];
- linhas 11–18: as opções para a solicitação HTTP a ser enviada (além das opções padrão já definidas nas linhas 5–6);
- linhas 14–17: os parâmetros de URL [action=init-session&type=json]. O objeto [params] será automaticamente convertido numa string codificada para URL;
- linha 22: chamada de bloqueio à função assíncrona [axios.request]. O primeiro parâmetro é a URL de destino construída como [main.php] anexada à URL base definida na linha 6. O segundo parâmetro é o objeto [options] das linhas 11–18;
- linha 25: [response] é um objeto JavaScript que encapsula toda a resposta HTTP do servidor (cabeçalhos HTTP + corpo da resposta). Exibimo-lo para ver a sua estrutura JavaScript;
- linha 27: se o servidor enviou um documento, este encontra-se em [response.data]. Aqui sabemos que o servidor envia uma resposta JSON acompanhada pelo cabeçalho HTTP [Content-type: application/json]. A presença deste cabeçalho faz com que [axios] deserialize automaticamente [response.data] num objeto JavaScript;
- linha 28: a função [axios] pode lançar uma exceção. É aqui que o [axios] difere do [fetch]. É lançada uma exceção nos seguintes casos:
- a solicitação HTTP não pôde ser enviada (erro do lado do cliente);
- o servidor enviou um código de erro HTTP (400, 404, 500, …) (este comportamento é, na verdade, configurável). Note que, se este código de estado HTTP for acompanhado por uma resposta, o [fetch] não lançou uma exceção, ao passo que o [axios] o faz. No entanto, se o código de erro HTTP for acompanhado por um documento, este é colocado em [error.response];
- linha 32: exibimos a estrutura JavaScript do objeto [error];
- linhas 33–38: se o objeto [error] contiver um objeto [response], essa resposta é devolvida ao código de chamada;
- linhas 39–42: em todos os outros casos, o objeto [error] é passado de volta para o código de chamada;
- linhas 47–57: a função assíncrona [main];
- linha 50: chamada bloqueante à função assíncrona [initSession]. A resposta JSON do servidor é recuperada como um objeto JavaScript;
- linhas 53–56: tratamento de eventuais erros. A mensagem de erro encontra-se em [error.message];
Os resultados da execução são os seguintes:
Caso 1: O servidor Laragon não está a funcionar
[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/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],
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 muita informação;
- [Error], linhas 3-9: uma descrição do erro que ocorreu;
- [config], linhas 10–27: a configuração do pedido HTTP que levou a este erro;
- [config.url], linhas 11–12: o URL de destino;
- [config.method], linha 13: método da solicitação;
- [config.params], linha 14: os parâmetros da URL;
- [config.headers], linhas 16–17: os cabeçalhos HTTP da solicitação;
- [config.baseURL], linha 18: o URL 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. Note que a maioria das propriedades é precedida por um sublinhado (_), indicando que são propriedades internas do objeto [request] não destinadas a serem usadas diretamente pelo programador;
- [response], linha 134: a resposta do servidor, que aqui está vazia;
- 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',
'état': 700,
'réponse': 'session démarrée avec type [json]' } }
succès ---------------------------------------------
réponse= { action: 'init-session',
'état': 700,
'réponse': 'session démarrée avec type [json]' } object
[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 de estado HTTP da resposta;
- linha 4, [statusText]: o texto associado ao código de estado 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 de documento enviado pelo servidor;
- linhas 14–31, [config]: a configuração do pedido HTTP enviado;
- 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: É enviada uma solicitação [init-session] incorreta para o 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',
'état': 703,
'réponse': 'paramètre type=[x] invalide' } },
isAxiosError: true,
toJSON: [Function] }
succès ---------------------------------------------
réponse= { action: 'init-session',
'état': 703,
'réponse': 'paramètre type=[x] invalide' } object
[Done] exited with code=0 in 0.69 seconds
Como o servidor respondeu com um código HTTP 400 (linha 15), o [axios] lançou uma exceção (mais uma vez, este comportamento é configurável). Embora o [axios] tenha lançado uma exceção, ainda obtemos a resposta HTTP do servidor em [error.response] (linha 14) e o documento JSON enviado em [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 detalhámos os objetos tratados pela biblioteca [axios] durante um pedido HTTP, podemos reescrever o script [axios-01] da seguinte forma:
'use strict';
import axios from 'axios';
// axios default configuration
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost/php7/scripts-web/impots/version-14';
// init session
async function initSession(axios) {
// query options HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
// URL parameters
params: {
action: 'init-session',
type: 'json'
}
};
try {
// execute query HTTP [get /main.php?action=init-session&type=json]
const response = await axios.request('main.php', options);
// the server response is in [response.data]
return response.data;
} catch (error) {
// server response
if (error.response) {
// the answer jSON is in [error.response.data]
return error.response.data;
} else {
// error restart
throw error;
}
}
}
// the main function executes the asynchronous function [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);
}
}
// test
main();
12.7. script [axios-03]
O script [axios-03] segue a mesma metodologia do script [axios-02]. Desta vez, adicionamos a solicitação HTTP [authenticate-user] ao servidor, que é feita utilizando uma solicitação POST:
'use strict';
import axios from 'axios';
import qs from 'qs'
// axios configuration
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost/php7/scripts-web/impots/version-14';
// init session
async function initSession(axios) {
// query options HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
// URL parameters
params: {
action: 'init-session',
type: 'json'
}
};
try {
// execute query HTTP [get /main.php?action=init-session&type=json]
const response = await axios.request('main.php', options);
// the server response is in [response.data]
return response.data;
} catch (error) {
// server response
if (error.response) {
// the answer jSON is in [error.response.data]
return error.response.data;
} else {
// error restart
throw error;
}
}
}
async function authentifierUtilisateur(axios, user, password) {
// query options HHTP [POST /main.php?action=authenticate-user]
const options = {
method: "POST",
headers: {
'Content-type': 'application/x-www-form-urlencoded',
},
// body of POST
data: qs.stringify({
user: user,
password: password
}),
// URL parameters
params: {
action: 'authentifier-utilisateur'
}
};
try {
// execute query HTTP [post /main.php?action=authenticate-user]
const response = await axios.request('main.php', options);
// the server response is in [response.data]
return response.data;
} catch (error) {
// server response
if (error.response) {
// the answer jSON is in [error.response.data]
return error.response.data;
} else {
// error restart
throw error;
}
}
}
// the main function executes asynchronous functions one by one
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);
// authenticate-user
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);
}
}
// test
main();
Comentários
- linhas 38-70: a função assíncrona [authenticateUser];
- linha 39: o pedido deve ser feito [POST /main.php?action=authenticate-user];
- linhas 40–54: as opções da solicitação HTTP;
- linha 41: esta é uma solicitação POST;
- linhas 42–44: os parâmetros POST serão codificados por URL num documento que o cliente envia com a sua solicitação;
- linhas 46–49: a propriedade [data] deve conter a string POST codificada por URL. Para isso, usamos a biblioteca [qs] importada na linha 3;
- linhas 55–69: para executar a solicitação, usamos o mesmo código do método [initSession];
- linhas 73–89: o método [asynchrone] chama sucessivamente os métodos [initSession] e [authentifierUtilisateur] de forma bloqueante, linhas 77 e 82;
- linha 82: o par (admin, admin) é utilizado como credenciais de login. Sabemos que 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',
'état': 700,
'réponse': 'session démarrée avec type [json]' }
action authentifier-utilisateur en cours ---------------------------------------------
succès ---------------------------------------------
réponse= { action: 'authentifier-utilisateur',
'état': 103,
'réponse':
[ 'pas de session en cours. Commencer par action [init-session]' ] }
[Done] exited with code=0 in 0.834 seconds
- linhas 9-12: falha na autenticação do utilizador: o servidor não reteve o facto de ter sido iniciada uma sessão JSON. Isto deve-se ao facto de o cookie de sessão enviado em resposta ao primeiro pedido [init-session] não ter sido reenviado;
12.8. script [axios-04]
O script [axios-04] introduz duas melhorias ao script [axios-03]:
- ele lida com o cookie de sessão;
- integra numa função [getRemoteData] o que é comum às funções [initSession] e [authenticateUser];
'use strict';
import axios from 'axios';
import qs from 'qs'
// axios configuration
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost/php7/scripts-web/impots/version-14';
// session cookie
const sessionCookieName = "PHPSESSID";
let sessionCookie = '';
// init session
async function initSession(axios) {
// query options HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
// URL parameters
params: {
action: 'init-session',
type: 'json'
}
};
// execute query HTTP
return await getRemoteData(axios, options);
}
async function authentifierUtilisateur(axios, user, password) {
// query options HHTP [post /main.php?action=authenticate-user]
const options = {
method: "POST",
headers: {
'Content-type': 'application/x-www-form-urlencoded',
},
// body of POST
data: qs.stringify({
user: user,
password: password
}),
// URL parameters
params: {
action: 'authentifier-utilisateur'
}
};
// execute query HTTP
return await getRemoteData(axios, options);
}
async function getRemoteData(axios, options) {
// for the session cookie
if (!options.headers) {
options.headers = {};
}
options.headers.Cookie = sessionCookie;
// execute query HTTP
let response;
try {
// asynchronous request
response = await axios.request('main.php', options);
} catch (error) {
// the [error] parameter is an exception instance - it can take various forms
if (error.response) {
// the server response is in [error.response]
response = error.response;
} else {
// error restart
throw error;
}
}
// response is the entire HTTP response from the server (HTTP headers + response itself)
// retrieve the session cookie if it exists
const setCookie = response.headers['set-cookie'];
if (setCookie) {
// setCookie is an array
// look for the session cookie in this table
let trouvé = false;
let i = 0;
while (!trouvé && i < setCookie.length) {
// look for the session cookie
const results = RegExp('^(' + sessionCookieName + '.+?);').exec(setCookie[i]);
if (results) {
// the session cookie is stored
// eslint-disable-next-line require-atomic-updates
sessionCookie = results[1];
// we found
trouvé = true;
} else {
// next item
i++;
}
}
}
// the server response is in [response.data]
return response.data;
}
// the main function executes asynchronous functions one by one
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);
// authenticate-user
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);
}
}
// test
main();
Comentários
- linhas 14–26: a função [initSession]. Agora, ela simplesmente prepara a solicitação HTTP a ser enviada ao servidor, mas não a executa. Ela delega essa tarefa 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 necessárias para executar um pedido HTTP:
- [axios], o objeto responsável por enviar a solicitação e receber a resposta;
- [options], as opções de configuração para a solicitação a ser enviada ao servidor;
- linha 59: execução da solicitação e espera pela resposta JSON;
- linhas 60–68: tratamento de eventuais exceções;
- linha 64: recuperar a resposta, que pode estar encapsulada no objeto de erro;
- linha 67: se o servidor lançou uma exceção sem incluir a resposta do servidor, então o erro recebido é propagado para o código de chamada;
- A função [getRemoteData] gere o cookie de sessão:
- armazena-o na variável [sessionCookie] (linha 11) quando o recebe pela primeira vez;
- depois devolve-o com cada novo pedido HTTP;
- linhas 72–92: [getRemoteData] analisa cada resposta do servidor para determinar se este enviou o cabeçalho HTTP [Set-Cookie]. Sabemos que o servidor envia um cookie de sessão denominado [PHPSESSID] (linha 10). Este é, portanto, o cookie que procuramos (linha 10);
- linha 72: recuperamos os cabeçalhos HTTP [Set-Cookie] se existirem (não distingue maiúsculas de minúsculas). Na verdade, pode haver vários cabeçalhos [Set-Cookie], pelo que recuperamos uma matriz;
- linha 73: se tiver sido recuperada uma matriz de cookies;
- linhas 78–90: procuramos o cookie de sessão entre todos os cookies da matriz;
- linha 80: a expressão relacional utilizada para procurar o cookie de sessão no cookie #i;
- linha 81: se a comparação devolveu resultados;
- linha 84: temos em results[1], o primeiro parêntese do padrão da expressão relacional, ou seja, (PHPSESSID=xxxx) até ao parêntese de fecho (não incluído) que encerra o cookie de sessão;
- linhas 50–54: em cada pedido, o cookie de sessão é incluído nos cabeçalhos HTTP do pedido. Na primeira vez, este cookie está vazio e, por isso, 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',
'état': 700,
'réponse': 'session démarrée avec type [json]' }
action authentifier-utilisateur en cours ---------------------------------------------
succès ---------------------------------------------
réponse= { action: 'authentifier-utilisateur',
'état': 200,
'réponse': 'Authentification réussie [admin, admin]' }
[Done] exited with code=0 in 0.982 seconds