12. Las funciones HTTP de JavaScript

12.1. Elección de una biblioteca HTTP
En este caso, hemos elegido dos bibliotecas:
EcmaScript 6 cuenta de forma nativa con una función llamada HTTP, que no está implementada por [node.js] (septiembre de 2019). Existe una biblioteca denominada [node-fetch] que permite utilizar la función [fetch] en Node. Esta biblioteca utiliza ciertas funciones propias de [node.js]. Por lo tanto, es posible que un código [node-fetch] no sea 100 % compatible en un entorno que no sea [node], como por ejemplo en un navegador;
Por otra parte, existe una biblioteca denominada [axios] dedicada a las consultas HTTP, compatible tanto con [node.js] como con los navegadores. Es esta biblioteca la que utilizaremos finalmente.
Vamos a presentar un mismo script escrito con estas dos bibliotecas para demostrar que el proceso de programación con ellas es similar.
12.2. Configuración del entorno de trabajo
12.2.1. Instalación del servidor de cálculo de impuestos
Finalmente, vamos a escribir una aplicación web con la siguiente arquitectura:

JS: JavaScript
El código JavaScript es del lado del cliente:
- de un servicio de páginas o fragmentos estáticos;
- de un servicio jSON;
Por lo tanto, el código JavaScript es un cliente jSON y, como tal, puede organizarse en capas [UI, métier, dao] (UI: Interfaz de usuario), al igual que nuestros clientes jSON escritos en PHP.
El servidor será el de cálculo de impuestos, del que ya hemos escrito 13 versiones. Vamos a escribir una decimocuarta. Por lo tanto, empezamos duplicando, en NetBeans, la carpeta de la versión 13 en la carpeta de la versión 14:

- en [6], modificamos el archivo [config.json] de la versión 14 de la siguiente manera:
{
"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"
}
- en la línea 3, cambiamos la carpeta raíz de la aplicación;
Para acceder a este servidor, hay que iniciar los servicios [Laragon].
Una vez hecho esto, podemos probar con [Postman] (véase el artículo en el enlace) esta nueva versión del servidor, idéntica por el momento a la versión 13. Podemos utilizar la colección de consultas empleadas para probar la versión 12 del servidor de cálculo de impuestos:

- en [1-4], utilizar la consulta [init-session-700] para iniciar una sesión jSON;
- en [4-5], sustituir [version-12] por [version-14] para probar la versión 14 del proyecto;
- al ejecutarlo, debemos recibir la respuesta jS0N [6] del servidor;
La versión 14 del servidor ya está operativa. Tendremos que modificarla ligeramente. Recordemos el API de este servidor:
Acción | Función | Contexto de ejecución |
init-session | Sirve para establecer el tipo (json, xml, html) de las respuestas deseadas | Solicitud GET main.php?action=init-session&type=x Se puede enviar en cualquier momento |
authentifier-utilisateur | Autoriza o no a un usuario a iniciar sesión | Solicitud POST main.php?action=authentifier-utilisateur La solicitud debe incluir dos parámetros enviados mediante POST [user, password] Solo se puede enviar si se conoce el tipo de sesión (json, xml, html) |
calcular-impuesto | Realiza una simulación del cálculo de impuestos | Solicitud POST main.php?action=calcular-impuestos La solicitud debe incluir tres parámetros POST: [marié, enfants, salaire] Solo se puede enviar si se conoce el tipo de sesión (json, xml, html) y el usuario está autenticado |
lister-simulations | Solicita ver la lista de simulaciones realizadas desde el inicio de la sesión | Solicitud GET main.php?action=lister-simulations La solicitud no admite ningún otro parámetro Solo se puede emitir si se conoce el tipo de sesión (json, xml, html) y el usuario está autenticado |
eliminar-simulación | Elimina una simulación de la lista de simulaciones | Consulta GET main.php?action=lister-simulations&número=x La consulta no admite ningún otro parámetro Solo se puede enviar si se conoce el tipo de sesión (json, xml, html) y el usuario está autenticado |
fin-session | Finaliza la sesión de simulaciones. | Técnicamente, se elimina la sesión web anterior y se crea una nueva Solo se puede emitir si se conoce el tipo de sesión (json, xml, html) y el usuario está autenticado |
12.2.2. Instalación de las bibliotecas HTTP del cliente JavaScript
En un primer momento, trabajaremos con la siguiente arquitectura:

- en [1], un script de consola [node.js] realiza una solicitud HTTP al servidor jSON de cálculo de impuestos;
- en [4], recibe esta respuesta y la muestra en la consola;
En el ejemplo n.º 1, utilizaremos las bibliotecas [node-fetch] y [axios]; posteriormente, solo conservaremos [axios] para los siguientes ejemplos. Ahora instalamos estas dos bibliotecas de JavaScript desde el terminal de [VSCode]:

También utilizaremos la biblioteca [qs], que permite la codificación URL de una cadena de caracteres. Recordemos que esta codificación se utiliza para codificar los parámetros de una solicitud HTTP, GET o POST.

12.3. script [fetch-01]
El script [fetch-01] utiliza la biblioteca [node-fetch] para inicializar una sesión jSON con el servidor de cálculo de impuestos. Su código es el siguiente:
'use strict';
// importaciones
import fetch from 'node-fetch';
import qs from 'qs';
import { sprintf } from 'sprintf-js';
import moment from 'moment';
// URL básico del servidor de cálculo de impuestos
const baseUrl = 'http://localhost/php7/scripts-web/impots/version-14/main.php?';
// inicialización de sesión
async function initSession() {
// opciones de la consulta HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
timeout: 2000
};
// ejecución de la consulta HTTP [get /main.php?action=init-session&type=json]
let débutFetch;
try {
// solicitud asíncrona: [fetch] devuelve una promesa
débutFetch = moment(Date.now());
const response = await fetch(baseUrl + qs.stringify({
action: 'init-session',
type: 'json'
}), options);
// [response] es la respuesta completa del servidor HTTP (encabezados HTTP + la propia respuesta)
// se muestra esta respuesta para ver su estructura
console.log(sprintf("réponse fetch formatée en json,=%j, %s", response, heure(débutFetch)));
console.log("réponse fetch en javascript=", response);
// Se pueden consultar las cabeceras HTTP
console.log("entêtes de la réponse=", response.headers);
// si la respuesta es de tipo application/json, la respuesta JSON del servidor se obtiene con la función asíncrona [response.json()]
// en este caso, el código que realiza la llamada obtiene un objeto [Promise]
// [await] permite obtener la respuesta [json] del servidor en lugar de su promesa
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;
// si la respuesta es de tipo «text/plain», la respuesta de texto del servidor se obtiene con [response.text()]
// en este caso, el código que realiza la llamada obtiene un objeto [Promise]
// [await] permite obtener la respuesta [texte] del servidor en lugar de su promesa
// const text = await response.text();
// console.log("respuesta de texto=", texto);
// return text;
} catch (error) {
// Estamos aquí porque el servidor ha enviado un código de error [404 Not Found, ...] acompañado de un cuerpo vacío; mostramos el error para ver su estructura
// o bien porque el cliente [fetch] ha lanzado una excepción (red inaccesible, etc.)
// se muestra la estructura del error
console.log(sprintf("error fetch en json=%j, %s", error, heure(débutFetch)));
console.log("error fetch en javascript=", typeof (error), error);
// se muestra el mensaje de error recibido
throw error.message;
}
}
// la función «main» ejecuta la función así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));
}
}
// prueba
main();
// utilidad para mostrar la hora y la duración
function heure(début) {
// hora actual
const now = moment(Date.now());
// formato de la hora
let result = "heure=" + now.format("HH:mm:ss:SSS");
// ¿Hay que calcular una duración?
if (début) {
const durée = now - début;
const milliseconds = durée % 1000;
const seconds = Math.floor(durée / 1000);
// formato de hora + duración
result = result + sprintf(", durée= %s seconde(s) et %s millisecondes", seconds, milliseconds);
}
// resultado
return result;
}
Comentarios
- las funciones HTTP de JavaScript son funciones asíncronas. Aquí aplicamos lo que hemos aprendido en la sección anterior (véase el enlace);
- línea 24: para esperar a que la respuesta de la función asíncrona [fetch] se publique en el bucle de eventos de [node.js], utilizamos la palabra clave [await]. Sabemos que esta instrucción debe estar en un código precedido por la palabra clave [async] (línea 13);
- líneas 13-56: encapsulamos el código HTTP en la función asíncrona [initSession];
- líneas 59-69: se utiliza una segunda función asíncrona, [main], para llamar de forma bloqueante (async / await) a la función asíncrona [initSession];
- línea 72: se invoca la función asíncrona [main];
- aunque todo el código parezca sincrónico, lo que se ejecutan son funciones asíncronas, pero de forma bloqueante;
- línea 19: para inicializar una sesión jSON con el servidor de cálculo de impuestos, hay que enviarle el comando HTTP [get /main.php?action=init-session&type=json]. Esto es lo que hace el código de las líneas 24-27. La sintaxis de [fetch] es la siguiente: [fetch(URL, options)] con:
- [URL]: la consulta URL;
- [options]: un objeto que define las opciones de la consulta. Es aquí, en particular, donde se definen los encabezados HTTP que se quieren enviar al equipo de destino;
- líneas 15-18: se definen las opciones de la consulta que se quiere realizar:
- [method]: queremos realizar un GET;
- [timeout]: queremos que el cliente [fetch] no espere más de 2 segundos la respuesta del servidor. Si se supera este plazo, [fetch] lanzará una excepción;
- línea 24: para obtener el URL [/main.php?action=init-session&type=json], se utiliza la biblioteca [qs] para obtener la codificación URL a partir de los parámetros [action,type] del GET. La cadena obtenida es [init-session&type=json], que podríamos haber construido nosotros mismos. Simplemente queríamos mostrar cómo obtener una cadena URL codificada;
- línea 24: la palabra clave [await] indica que aquí se inicia una tarea asíncrona y que se espera a que publique su respuesta en el bucle de eventos de [node.js];
- línea 24: en [response], se obtiene un objeto complejo que describe la respuesta completa HTTP recibida (encabezados y documento);
- líneas 30-31: se muestra el objeto [response] para ver su estructura, primero como cadena de caracteres y luego como objeto de JavaScript;
- línea 33: se muestran los encabezados HTTP enviados por el servidor;
- línea 38: sabemos que el servidor de cálculo de impuestos va a enviar una cadena jSON. Esta está encapsulada en el objeto [response]. Podemos obtenerla con el método [response.json()]. Sin embargo, este método es asíncrono. Por lo tanto, se escribe [await response.json()] para obtener la cadena jSON, que se publicará en el bucle de eventos de [node.js]. De hecho, lo que se obtiene no es la cadena jSON, sino el objeto JavaScript representado por ella;
- línea 39: visualización de la cadena jSON recibida;
- línea 40: se devuelve el objeto JavaScript recibido;
- línea 47: se intercepta un posible error de la instrucción [fetch]. Esta solo lanza una excepción si la operación HTTP no se ha podido completar y no se ha recibido ninguna respuesta del servidor. Si se ha recibido una respuesta, incluso con un código HTTP diferente de [200 OK], [fetch] no lanza ninguna excepción y la respuesta del servidor estará disponible en la línea 38;
- líneas 51-52: se muestra el objeto [error] recibido por la cláusula [catch], primero como una cadena jSON y luego como un objeto JavaScript;
- línea 54: el mensaje de error de [fetch] se encuentra en [error.message];
- líneas 59-69: la función asíncrona [main] invoca la función asíncrona [initSession] de forma bloqueante (await en la línea 62);
- línea 72: se inicia la función asíncrona [main] y, a continuación, finaliza el código principal del script. El script global finalizará cuando las tareas asíncronas iniciadas hayan publicado sus resultados en el bucle de eventos;
Los resultados de la ejecución son los siguientes:
Caso 1: el servidor Laragon no está en marcha
[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:
'tiempo de espera de red agotado en: 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 cadena
[Done] exited with code=0 in 2.804 seconds
Comentarios
- línea 3: la solicitud HTTP falla tras 2 segundos y 62 milisegundos debido al tiempo de espera de 2 segundos que se había impuesto a la solicitud HTTP;
- líneas 4-9: el objeto JavaScript [error] interceptado por la cláusula [catch(error)]. Este objeto tiene dos propiedades:
- [FetchError]: línea 4;
- [message]: líneas 10-12;
- línea 14: el mensaje de error recibido por la función asíncrona [main];
Caso 2: el servidor Laragon se ha iniciado
[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',
'estado': 700,
'respuesta': 'sesión iniciada con el tipo [json]' } objeto
[Done] exited with code=0 in 1.022 seconds
Comentarios
- línea 3: [fetch] recibe la respuesta del servidor tras 375 ms;
- líneas 4-39: la estructura del objeto JavaScript [response] que encapsula la respuesta del servidor. Entre sus propiedades, algunas pueden resultarnos de interés:
- [status] (línea 25): código HTTP de la respuesta del servidor;
- [statusText] (línea 26): texto asociado a este código;
- [headers] (línea 27): los encabezados HTTP de la respuesta del servidor;
- [body] (línea 8): representa el documento enviado por el servidor. La instrucción [fetch] ofrece métodos para procesarlo;
- líneas 29-39: los encabezados HTTP de la respuesta del servidor;
- línea 40: la función asíncrona [response.json()] ha publicado su respuesta al cabo de 1 milisegundo;
- líneas 42-44: el objeto JavaScript recibido por la función asíncrona [main];
Caso 3: el servidor Laragon se ha iniciado, pero se le envía un comando erróneo:

- En la línea 26 anterior, se pasa un tipo de sesión erróneo al servidor;
Los resultados de la ejecución son los siguientes:
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,
'respuesta': 'parámetro type=[x] no válido' } objeto
[Done] exited with code=0 in 0.712 seconds
- la respuesta del servidor se recibe en la línea 2;
- línea 24: se puede observar que el código HTTP de la respuesta del servidor es 400, un código de error. Sin embargo, [fetch] no ha lanzado ninguna excepción. Mientras [fetch] reciba una respuesta del servidor, la procesa y no lanza ninguna excepción;
- líneas 41-43: la respuesta obtenida por la función asíncrona [main];
12.4. script [fetch-02]
El siguiente script retoma el script [fetch-01] y lo depura de todos los detalles innecesarios:
'use strict';
// importaciones
import fetch from 'node-fetch';
import qs from 'qs';
// URL base del servidor de cálculo de impuestos
const baseUrl = 'http://localhost/php7/scripts-web/impots/version-14/main.php?';
// inicialización de sesión
async function initSession() {
// opciones de la consulta HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
timeout: 2000
};
// ejecución de la consulta HTTP [get /main.php?action=init-session&type=json]
const response = await fetch(baseUrl + qs.stringify({
action: 'init-session',
type: 'json'
}), options);
// resultado recibido en jSON
return await response.json();
}
// la función «main» ejecuta la función así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);
}
}
// prueba
main();
Resultados de una ejecución 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,
'respuesta: 'sesión iniciada con el tipo [json]' }
[Done] exited with code=0 in 0.56 seconds
Resultados de una ejecución con excepción (se detiene el 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]
Aquí retomamos el script [fetch-01], que reescribimos con la biblioteca [axios]. Recordemos que nuestro interés por esta biblioteca radica en que sea compatible entre el entorno [node.js] y los de los navegadores habituales. Esto permite:
- en una primera fase, probar nuestros scripts en un entorno [node.js];
- en una fase 2, portarlos a un navegador;
El script [axios-01] retoma la estructura del script [fetch-01]:
'use strict';
import axios from 'axios';
// configuración predeterminada de axios
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost/php7/scripts-web/impots/version-14';
// inicialización de sesión
async function initSession(axios) {
// opciones de la solicitud HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
// parámetros de la consulta URL
params: {
action: 'init-session',
type: 'json'
}
};
// ejecución de la consulta HTTP [get /main.php?action=init-session&type=json]
try {
// solicitud asíncrona
const response = await axios.request('main.php', options);
//: la respuesta es el conjunto completo de la respuesta HTTP del servidor (encabezados HTTP + la propia respuesta)
// se muestra esta respuesta para ver su estructura
console.log("réponse axios=", response);
// la respuesta del servidor se encuentra en [response.data]
return response.data;
} catch (error) {
// nos encontramos aquí porque el servidor ha enviado un código de error [404 Not Found, 500 Internal Server Error, ...]
// el parámetro [error] es una instancia de excepción; puede adoptar diversas formas
// se muestra para ver su estructura
console.log("axios error=", typeof (error), error);
if (error.response) {
// el servidor ha señalado un error en el estado HTTP, pero también ha enviado una respuesta
// por lo que esta se encuentra en [error.response.data]
// Sabemos que el servidor envía respuestas jSON con la estructura {acción, estado, respuesta}
// y que, en caso de error, el mensaje de error se encuentra en [réponse]
return error.response.data;
} else {
// se genera el error
throw error;
}
}
}
// la función main ejecuta la función así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);
}
}
// prueba
main();
Comentarios
- línea 2: se importa la biblioteca [axios];
- líneas 5-6: configuración por defecto de las consultas HTTP. Las opciones de [axios.defaults] son válidas para todas las consultas HTTP emitidas por el objeto [axios], sin necesidad de volver a especificarlas en cada nueva consulta;
- línea 5: tiempo de espera de 2 segundos para todas las solicitudes;
- línea 6: todas las URL se expresarán en relación con la URL básica;
- línea 9: la función asíncrona [initSession];
- líneas 11-18: las opciones de la solicitud HTTP que se va a enviar (además de las opciones predeterminadas ya definidas en las líneas 5-6);
- líneas 14-17: los parámetros de URL [action=init-session&type=json]. El objeto [params] se transformará automáticamente en una cadena de caracteres codificada URL;
- línea 22: llamada bloqueante a la función asíncrona [axios.request]. El primer parámetro es el objeto de destino URL, construido a partir de [main.php] sumado al objeto base URL definido en la línea 6. El segundo parámetro es el objeto [options] de las líneas 11-18;
- línea 25: [response] es un objeto JavaScript que encapsula la respuesta completa HTTP del servidor (encabezados HTTP + documento de respuesta). Se muestra para ver su estructura JavaScript;
- línea 27: si el servidor ha enviado un documento, este se encuentra en [response.data]. En este caso, sabemos que el servidor envía una respuesta jSON acompañada de los encabezados HTTP y [Content-type : application/json]. La presencia de este encabezado hace que [axios] deserialice automáticamente [response.data] en un objeto JavaScript;
- línea 28: la función [axios] puede lanzar una excepción. Aquí es donde [axios] difiere de [fetch]. Se lanza una excepción en los siguientes casos:
- no se ha podido enviar la solicitud HTTP (error del lado del cliente);
- El servidor ha enviado un código de error HTTP (400, 404, 500, …) (este aspecto es, de hecho, configurable). Cabe recordar que, si este código de error HTTP va acompañado de una respuesta, [fetch] no generaba ninguna excepción, mientras que [axios] sí lo hacía. No obstante, si el código de error HTTP va acompañado de un documento, este se coloca en [error.response];
- línea 32: se muestra la estructura JavaScript del objeto [error];
- líneas 33-38: si el objeto [error] contiene un objeto [response], entonces es esta respuesta la que se devuelve al código que realiza la llamada;
- líneas 39-42: en los demás casos, se devuelve el objeto [error] al código que realiza la llamada;
- líneas 47-57: la función asíncrona [main];
- línea 50: llamada bloqueante a la función asíncrona [initSession]. Se recupera la respuesta jSON del servidor como un objeto JavaScript;
- líneas 53-56: interceptación de un posible error. El mensaje de error se encuentra en [error.message];
Los resultados de la ejecución son los siguientes:
Caso 1: el servidor Laragon no se ha iniciado
[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
Comentarios
- líneas 33-136: el objeto [error] contiene mucha información;
- [Error], líneas 3-9: una descripción del error que se ha producido;
- [config], líneas 10-27: la configuración de la consulta HTTP que provocó este error;
- [config.url], líneas 11-12: el destino URL;
- [config.method], línea 13: método de la consulta;
- [config.params], línea 14: los parámetros de URL;
- [config.headers], líneas 16-17: los encabezados HTTP de la consulta;
- [config.baseURL], línea 18: el URL de base del URL de destino;
- [config.timeout], línea 21: el tiempo de espera de la solicitud;
- [code], línea 28: un código de error;
- [request], líneas 29-133: una descripción detallada de la solicitud HTTP. Cabe destacar que la mayoría de las propiedades llevan el prefijo de un guión bajo _, lo que indica que se trata de propiedades internas del objeto [request] que no están destinadas a ser utilizadas directamente por el desarrollador;
- [response], línea 134: la respuesta del servidor, que en este caso no existe;
- línea 138: el mensaje de error mostrado por la función [main];
Caso 2: el servidor Laragon está en ejecución
[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,
'respuesta': 'sesión iniciada con el tipo [json]' } }
succès ---------------------------------------------
réponse= { action: 'init-session',
'estado': 700,
'respuesta': 'sesión iniciada con el tipo [json]' } objeto
[Done] exited with code=0 in 1.115 seconds
Comentarios
- líneas 3-203: el objeto JavaScript [response] que encapsula la respuesta HTTP del servidor;
- línea 3, [status]: el código HTTP de la respuesta;
- línea 4, [statusText]: el texto asociado al código HTTP anterior;
- líneas 5-13, [headers]: los encabezados HTTP de la respuesta:
- línea 10, [Set-Cookie]: la cookie de sesión;
- línea 13, [Content-Type]: el tipo de documento enviado por el servidor;
- líneas 14-31, [config]: la configuración de la solicitud HTTP enviada;
- líneas 32-199, [request]: el objeto JavaScript que detalla la solicitud HTTP enviada;
- líneas 200-203, [request.data]: el objeto JavaScript que encapsula la respuesta jSON del servidor;
- líneas 205-207: la respuesta recuperada por la función asíncrona [main];
Caso 3: se realiza una solicitud errónea [init-session] al servidor Laragon;

Los resultados de la ejecución son los siguientes:
[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',
'«estado»: 703,
'respuesta: 'parámetro type=[x] no válido' } },
isAxiosError: true,
toJSON: [Function] }
succès ---------------------------------------------
réponse= { action: 'init-session',
'estado': 703,
'respuesta': 'parámetro type=[x] no válido' } objeto
[Done] exited with code=0 in 0.69 seconds
Dado que el servidor respondió con un código HTTP 400 (línea 15), [axios] lanzó una excepción (una vez más, este comportamiento es configurable). Aunque [axios] lanzó una excepción, sí se obtiene la respuesta HTTP del servidor en [error.response] (línea 14) y el documento jSON enviado a [error.response.data] (línea 34). Líneas 41-43: la función [main] recupera correctamente la respuesta jSON del servidor.
12.6. script [axios-02]
Ahora que hemos detallado los objetos que maneja la biblioteca [axios] durante una consulta HTTP, podemos reescribir el script [axios-01] de la siguiente manera:
'«use strict»;
import axios from 'axios';
// configuración predeterminada de axios
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost/php7/scripts-web/impots/version-14';
// inicialización de sesión
async function initSession(axios) {
// opciones de la solicitud HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
// parámetros de la consulta URL
params: {
action: 'init-session',
type: 'json'
}
};
try {
// ejecución de la consulta HTTP [get /main.php?action=init-session&type=json]
const response = await axios.request('main.php', options);
// la respuesta del servidor se encuentra en [response.data]
return response.data;
} catch (error) {
// respuesta del servidor
if (error.response) {
// la respuesta jSON se encuentra en [error.response.data]
return error.response.data;
} else {
// se vuelve a generar el error
throw error;
}
}
}
// la función «main» ejecuta la función así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);
}
}
// prueba
main();
12.7. script [axios-03]
El script [axios-03] sigue la misma metodología que el script [axios-02]. En esta ocasión, se añade la solicitud HTTP [authentifier-utilisateur] al servidor, lo cual se realiza mediante un POST:
'«use strict»;
import axios from 'axios';
import qs from 'qs'
// configuración de Axios
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost/php7/scripts-web/impots/versión-14';
// iniciar sesión
async function initSession(axios) {
// opciones de la solicitud HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
// parámetros de la consulta URL
params: {
action: 'init-session',
type: 'json'
}
};
try {
// ejecución de la consulta HTTP [get /main.php?action=init-session&type=json]
const response = await axios.request('main.php', options);
// la respuesta del servidor se encuentra en [response.data]
return response.data;
} catch (error) {
// respuesta del servidor
if (error.response) {
// la respuesta jSON se encuentra en [error.response.data]
return error.response.data;
} else {
// se vuelve a generar el error
throw error;
}
}
}
async function authentifierUtilisateur(axios, user, password) {
// opciones de la solicitud HHTP [POST /main.php?action=authentifier-utilisateur]
const options = {
method: "POST",
headers: {
'«Content-type»: «application/x-www-form-urlencoded»,
},
// cuerpo del POST
data: qs.stringify({
user: user,
password: password
}),
// parámetros de la URL
params: {
action: 'authentifier-utilisateur'
}
};
try {
// ejecución de la consulta HTTP [post /main.php?action=authentifier-utilisateur]
const response = await axios.request('main.php', options);
// la respuesta del servidor se encuentra en [response.data]
return response.data;
} catch (error) {
// respuesta del servidor
if (error.response) {
// la respuesta jSON se encuentra en [error.response.data]
return error.response.data;
} else {
// se vuelve a generar el error
throw error;
}
}
}
// la función «main» ejecuta las funciones asíncronas una por una
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-usuario
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);
}
}
// prueba
main();
Comentarios
- líneas 38-70: la función asíncrona [authentifierUtilisateur];
- línea 39: hay que realizar la consulta [POST /main.php?action=authentifier-utilisateur];
- líneas 40-54: las opciones de la consulta HTTP;
- línea 41: se trata de un POST;
- líneas 42-44: los parámetros de POST se codificarán en un documento que el cliente envía junto con su solicitud;
- líneas 46-49: la propiedad [data] debe contener la cadena codificada de POST URL. Para ello, aquí se utiliza la biblioteca [qs] importada en la línea 3;
- líneas 55-69: para la ejecución de la consulta, se utiliza el mismo código que en el método [initSession];
- líneas 73-89: el método [asynchrone] llama sucesivamente, de forma bloqueante, a los métodos [initSession, authentifierUtilisateur], líneas 77 y 82;
- línea 82: se utiliza el par (admin, admin) como credenciales de conexión. Sabemos que el servidor las reconoce;
Los resultados de la ejecución son los siguientes:
[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',
'«estado»: 700,
'respuesta: 'sesión iniciada con el tipo [json]' }
action authentifier-utilisateur en cours ---------------------------------------------
succès ---------------------------------------------
réponse= { action: 'authentifier-utilisateur',
'estado': 103,
'respuesta':
[ 'pas de session en cours. Commencer par action [init-session]' ] }
[Done] exited with code=0 in 0.834 seconds
- líneas 9-12: la autenticación del usuario falla: el servidor no ha registrado que se había iniciado una sesión jSON. Esto se debe a que no se ha reenviado la cookie de sesión enviada en respuesta a la primera solicitud [init-session];
12.8. script [axios-04]
El script [axios-04] aporta dos mejoras al script [axios-03]:
- gestiona la cookie de sesión;
- factoriza en una función [getRemoteData] lo que es común a las funciones [initSession] y [authentifierUtilisateur];
'use strict';
import axios from 'axios';
import qs from 'qs'
// configuración de Axios
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost/php7/scripts-web/impots/version-14';
// cookie de sesión
const sessionCookieName = "PHPSESSID";
let sessionCookie = '';
// inicialización de sesión
async function initSession(axios) {
// opciones de la solicitud HHTP [get /main.php?action=init-session&type=json]
const options = {
method: "GET",
// parámetros de la consulta URL
params: {
action: 'init-session',
type: 'json'
}
};
// ejecución de la consulta HTTP
return await getRemoteData(axios, options);
}
async function authentifierUtilisateur(axios, user, password) {
// opciones de la solicitud HHTP [post /main.php?action=authentifier-utilisateur]
const options = {
method: "POST",
headers: {
'«Content-type»: «application/x-www-form-urlencoded»,
},
// cuerpo del POST
data: qs.stringify({
user: user,
password: password
}),
// parámetros de la URL
params: {
action: 'authentifier-utilisateur'
}
};
// ejecución de la solicitud HTTP
return await getRemoteData(axios, options);
}
async function getRemoteData(axios, options) {
// para la cookie de sesión
if (!options.headers) {
options.headers = {};
}
options.headers.Cookie = sessionCookie;
// ejecución de la solicitud HTTP
let response;
try {
// solicitud asíncrona
response = await axios.request('main.php', options);
} catch (error) {
// el parámetro [error] es una instancia de excepción; puede adoptar diversas formas
if (error.response) {
// la respuesta del servidor se encuentra en [error.response]
response = error.response;
} else {
// Se vuelve a generar el error
throw error;
}
}
//: la respuesta es el conjunto completo de la respuesta HTTP del servidor (encabezados HTTP + la propia respuesta)
// se recupera la cookie de sesión, si existe
const setCookie = response.headers['set-cookie'];
if (setCookie) {
// setCookie es una matriz
//: se busca la cookie de sesión en este array
let trouvé = false;
let i = 0;
while (!trouvé && i < setCookie.length) {
// se busca la cookie de sesión
const results = RegExp('^(' + sessionCookieName + '.+?);').exec(setCookie[i]);
if (results) {
// se almacena la cookie de sesión
// eslint-disable-next-line require-atomic-updates
sessionCookie = results[1];
// la hemos encontrado
trouvé = true;
} else {
// el siguiente elemento
i++;
}
}
}
// la respuesta del servidor está en [response.data]
return response.data;
}
// la función «main» ejecuta las funciones asíncronas una por una
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-usuario
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);
}
}
// prueba
main();
Comentarios
- líneas 14-26: la función [initSession]. Ahora se limita a preparar la consulta HTTP para enviarla al servidor, pero no la ejecuta. Confía esta tarea al método [getRemoteDate] de las líneas 49-95;
- líneas 28-47: la función [authentifierUtilisateur] sigue el mismo procedimiento;
- línea 49: la función [getRemoteData] recibe los dos datos que le permiten ejecutar una solicitud HTTP:
- [axios], el objeto que se encargará de enviar la consulta y recibir la respuesta;
- [options], las opciones de configuración de la consulta que se va a enviar al servidor;
- línea 59: ejecución de la consulta y espera bloqueante de su respuesta jSON;
- líneas 60-68: gestión de la posible excepción;
- línea 64: se recupera la respuesta, que puede estar encapsulada en el objeto de error;
- línea 67: si el servidor ha lanzado una excepción sin incluir en ella la respuesta del servidor, se reenvía el error recibido al código que lo ha llamado;
- la función [getRemoteData] gestiona la cookie de sesión:
- lo almacena en la variable [sessionCookie] (línea 11) cuando lo recibe por primera vez;
- a continuación, lo devuelve con cada nueva solicitud HTTP;
- líneas 72-92: [getRemoteData] analiza cada respuesta del servidor para comprobar si ha enviado el encabezado HTTP [Set-Cookie]. Sabemos que el servidor envía una cookie de sesión denominada [PHPSESSID] (línea 10). Por lo tanto, es esta cookie la que buscamos (línea 10);
- línea 72: se recuperan los encabezados HTTP y [Set-Cookie] si existen (no importa si se escriben en mayúsculas o minúsculas). De hecho, puede haber varias cabeceras [Set-Cookie], por lo que lo que se recupera es un array;
- línea 73: si se ha recuperado una matriz de cookies;
- líneas 78-90: se busca la cookie de sesión entre todas las cookies del array;
- línea 80: la expresión relacional que permite buscar la cookie de sesión en la cookie n.º i;
- línea 81: si la comparación ha devuelto resultados;
- línea 84: en results[1] tenemos el primer paréntesis del patrón de la expresión relacional, es decir, (PHPSESSID=xxxx) hasta el punto y coma (no incluido) que finaliza la cookie de sesión;
- líneas 50-54: en cada solicitud, la cookie de sesión se incluye en los encabezados HTTP de la solicitud. La primera vez, esta cookie está vacía y, por lo tanto, el servidor la ignorará;
Los resultados de la ejecución son los siguientes:
[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,
'respuesta: 'sesión iniciada con el tipo [json]' }
action authentifier-utilisateur en cours ---------------------------------------------
succès ---------------------------------------------
réponse= { action: 'authentifier-utilisateur',
'estado': 200,
'respuesta': 'Autenticación correcta [admin, admin]' }
[Done] exited with code=0 in 0.982 seconds