Saltar al contenido principal

Remote - Cliente HTTP

Introducción​

A menudo, en nuestras aplicaciones, necesitamos hacer peticiones HTTP a servicios externos. Esto se puede hacer utilizando el recurso _remote.

Para realizar llamadas HTTP internamente a otros servicios o servidores internos en el equipo, o para llamar a algún servicio en internet, el uso del recurso Remote es esencial.

Consulte la documentación del recurso Remote.

Incluso podemos enviar y recibir datos en JSON y subir o descargar archivos.

Inicialización​

Para poder realizar una llamada HTTP, primero debemos iniciarla; para ello utilizaremos el método init de _remote y luego guardaremos el resultado de esta operación en una variable llamada remoto para poder referenciar la petición:

// Admite enviar parámetros HTTP
const remotoSimple = _remote.init();
// Admite enviar JSON:
const remotoJSON = _remote.init().asJSON();

Configuración​

También podemos definir configuraciones globales en la aplicación; observe este ejemplo completo:

...
"remote": {
"ejemplo-basic-auth": {
"url": "https://ejemplo.com/api/rest/ejemplo",
"form": true,
"authorization": {
"username": "admin",
"password": "clave"
},
"data": {
"param1": "valor 1...",
"param2": "valor 2..."
}
},
"ejemplo-auth-token": {
"urlPrefix": "https://ejemplo.com/api",
"json": true,
"authorization": "Bearer TOKEN-DE-AUTORIZACIÓN-AQUÍ",
"connectTimeout": 5000,
"readTimeout": 60000,
}
},
...

Podemos configurar un prefijo de URL (urlPrefix) o la URL completa (url).

Podemos definir si la petición, por defecto, debe enviar los datos como formulario o JSON.

Admite enviar autorización básica con usuario y contraseña o token.

Y es posible definir los datos predeterminados que se enviarán (data), así como los tiempos límite de conexión (connectTimeout) y de lectura (readTimeout).

Cómo usar​

Para utilizar el recurso Remote con las configuraciones definidas en la aplicación, basta con iniciar el recurso con la clave de la configuración; por ejemplo:

const respuesta = _remote.init("ejemplo-basic-auth").post();

Y en caso de que se defina la URL de prefijo:

const remoto = _remote.init("ejemplo-auth-token");
const respuesta = remoto.post(
"/services/carga-datos",
_val.map()
.set("param1", "valor 1")
.set("param2", "valor 2")
);

Petición HTTP​

Vea cómo podemos iniciar una petición HTTP utilizando el recurso Remote.

Enviar JSON​

Para enviar datos en formato JSON necesitamos indicar el tipo de contenido como JSON:

La forma sencilla de hacerlo es utilizando el método asJSON(), por ejemplo:

const remoto = _remote.init().asJSON();
remoto.setURL("http://ejemplo.com/guardar");
const respuesta = remoto.post(
_val.map()
.set("datos", "ejemplo")
.set("json", true)
);

Así, los datos se enviarán como JSON para los métodos HTTP POST y PUT, pero para GET y DELETE los datos siempre se envían en la querystring porque, para estos métodos, el protocolo HTTP no admite que se incluya un cuerpo con datos.

Métodos HTTP​

No necesitamos indicar explícitamente en la cabecera de la llamada su método HTTP; para ello, nuestra referencia de la llamada dispone de una función propia para cada tipo de método HTTP:

const remoto = _remote.init();

remoto.setURL("http://ejemplo.com");

remoto.get(); // para llamadas GET
remoto.post(); // para llamadas POST
remoto.put(); // para llamadas PUT
remoto.delete(); // para llamadas DELETE

Cabecera HTTP​

Para configurar los parámetros de la cabecera HTTP podemos definir las claves con el método getHeader(), por ejemplo:

const remoto = _remote.init();

remoto.getHeader().set("CLAVE", "VALOR");

URL de la petición​

Para indicar la URL de la petición basta con pasarla como primer parámetro de las funciones de los respectivos métodos HTTP:

const remoto = _remote.init().asJSON()

remoto.get("http://ejemplo.com") // para llamadas GET
remoto.post("http://ejemplo.com") // para llamadas POST
remoto.put("http://ejemplo.com") // para llamadas PUT
remoto.delete("http://ejemplo.com") // para llamadas DELETE

Añadir datos a la petición​

Si necesita añadir datos al cuerpo de la petición, basta con pasarlos como segundo parámetro de la función del método correspondiente:

const remoto = _remote.init().asJSON();

remoto.get("http://ejemplo.com", _val.map().set("id_usuario", 1)); // para llamadas GET
remoto.post("http://ejemplo.com", _val.map().set("id_usuario", 1)); // para llamadas POST
remoto.put("http://ejemplo.com", _val.map().set("id_usuario", 1)); // para llamadas PUT
remoto.delete("http://ejemplo.com", _val.map().set("id_usuario", 1)); // para llamadas DELETE

Respuesta​

Después de recibir la respuesta de la petición podemos leer sus datos utilizando el método json o content:

const remoto = _remote.init().asJSON();

const respuesta = remoto.post(
"http://ejemplo.com",
_val.map().set("id_usuario", 1)
);

if (respuesta.ok()) {
_log.info("Respuesta en JSON", respuesta.json());
} else {
_log.info("Falló con el estado: "+ respuesta.statusCode(), respuesta.content());
}

En la respuesta, con la función json() obtenemos el array o el objeto proporcionado como Values, y con la función content() obtenemos contenido en texto sin procesar o el HTML; el número del código de estado recibido viene en statusCode(), mientras que ok() devuelve un valor booleano que es verdadero si el código de estado está dentro del intervalo entre 200 y 299.

Descarga​

Para descargar archivos utilizamos Remote con asBinary() para indicar que debe ser una transferencia binaria.

Vea este ejemplo de servicio completo:

server/services/descarga-archivo.js
const descarga = _remote.asBinary()
.get('https://raw.githubusercontent.com/netuno-org/platform/main/docs/images/overview.png');

if (!descarga.ok()) {
_log.error(`Estado de la descarga del archivo: ${descarga.statusCode()}\n${descarga.toString()}`);
_header.status(500);
_out.json({resultado: false, error: 'descarga-archivo-fallida'});
_exec.stop();
}

const archivo = descarga.file();
_log.info(`Nombre del archivo descargado: ${archivo.name()}`);

archivo.save(_app.file(`storage/filesystem/server/${archivo.name()}`));
archivo.save(_storage.filesystem("server", "otro.png").file());
archivo.save(_os.file("/tmp/descarga.png"));
_out.json({resultado: true});

El archivo.save se utiliza 3 veces a propósito; para saber más sobre _app.file, _storage y _os.file, consulte el tutorial sobre Manipulación de Archivos y Carpetas.

Subida​

Para enviar un archivo estructurado como formulario en formato multipart, utilizamos asMultipartFormData().

Vea el ejemplo completo de un servicio:

server/services/subida-archivo.js
const archivo = _app.file("public/imagenes/logo.png");

const subida = _remote.asMultipartFormData()
.post(
'http://localhost:9000/services/receptor-archivo',
_val.map()
.set("archivo", archivo)
);

if (subida.ok()) {
_log.info(`Subida correcta: ${archivo.name()}`);
_out.json({resultado: true});
} else {
_log.error(`Estado de la subida del archivo: ${subida.statusCode()}\n${subida.toString()}`);
_header.status(500);
_out.json({resultado: false, error: 'subida-archivo-fallida'});
}

Observe que en el ejemplo anterior el archivo se envía a otro servicio; vea cómo se puede implementar en Netuno este otro servicio que recibe el archivo:

server/services/receptor-archivo.js
const archivo = _req.getFile("archivo");
_log.info(`Nombre del archivo recibido: ${archivo.name()}`);
archivo.save(_storage.filesystem("server", "recibido.png").file());
_out.json({resultado: true});

Conclusión​

Con el recurso Remote podemos integrar API externas, podemos exportar, importar o sincronizar datos.

Incluso podemos integrar servicios implementados en otras tecnologías, lo que permite realizar operaciones específicas proporcionadas por otros lenguajes.