@arcaelas/bridge v1.17.0
Bridge
¿Qué significa serverless?
La computación sin servidor (serverless por sus siglas en ingles) es un modelo de desarrollo en el que un proveedor en la nube (AWS, Azure, Google Cloud Platform, entre otros) es responsable de ejecutar un fragmento de código mediante la asignación dinámica de los recursos.
¿Como implementar servicios de Serverless?
Existen varias alternativas, entre las mas comunes tenemos:
- Firebase
- Google Cloud
- Microsoft Azure
- Amazon Web Services
- Serverless Frameworks
La documentación asociada a cada uno de estos servicios, se encuentra en el sitio oficial del los responsables.
¿Que nos ofrece un Serverless?
Suministro ágil de los recursos en tiempo real, incluso en caso de picos de carga imprevisibles o un crecimiento desproporcionado |
¿Que es Bridge de Arcaelas Insiders?
Los bridge (Puentes) son una estructura de código que permite a los desarrolladores interceptar solicitudes y respuestas del cliente/servidor, comunmente se utilizan con servicios de ServerLess (leer arriba).
Por este motivo Arcaelas Insiders desarrollado un "Bridge Extensible" para realizar estas tareas, las estructura implementada en nuestra librería se asemeja mucho a Express JS, aún si ya conoces de la estructura de ExpressJS te recomendamos continuar la lectura de este documento.
Primeros pasos
Antes de comenzar a utilizar nuestra librería será necesario instalarla:
npm i --save @arcaelas/bridge
Importación
import Bridge from '@arcaelas/bridge'
// or
const Bridge = require('@arcaelas/bridge');
El tipado se incluye dentro del modulo, no se requiere instalación adicional.
Inicialización
const router = new Bridge();
Ahora bien, si queremos anexar procesadores genéricos para nuestra solicitud, podríamos utilizar el método use() del Objeto router.
Vamos a interceptar todas las solicitudes al router y verificaremos que contengan un token de Autenticación en las cabeceras de la solicitud.
router.use((req, res, next)=>{
// Verificamos que se haya enviado el token de sesión
if( !req.headers.has("Authenticate") )
next( new Error("Se requiere una sesión iniciada"), 401 );
else next();
});
Descripción del ejemplo:
Si se envió algun token se continúa procesando la solicitud, en caso opuesto se detiene el proceso y se resuelve la solicitud con un error (Se requiere una sesión iniciada) y un código de Error HTTP (401 - Unauthorized).
El código de error es opcional, podríamos no incluirlo (por defecto es 502 - Bad Gateway).
- El error enviado a travéz de la función next() podría ser de tipo string siempre y cuando sea distinto a route.
- Llamamos next() al fallar la verificación, esto se debe a que los bridge interceptan las solicitudes solo una vez para evitar bucles infinitos o errores de memoria
- Tener en cuenta que llamar la función next() NO detiene el progreso de la función, esto quiere decir que el código después de next() se sigue leyendo, para evitar el progreso de la función se recomienda utilizar
return next();
en caso de ser necesario.
Asumiendo que nuestro router posee un CRUD de productos, vamos a incluír el siguiente código como ejemplo:
// Si tienes el ejemplo anterior incluído en tu código ya no será necesario verificar la sesión.
router.post("/products", async (req, res, next)=>{
/* Necesitas clonar la solicitud para evitar la ruptura del stream */
req = req.clone()
const db = window.localStorage;
const products = JSON.parse(db.getItem("products") || '[]');
/* No realizamos esta conversión de datos de forma automática debido a ciertas incompatibilidades con los posibles valores de BodyInit, pero en un futuro no muy lejano agregaremos más funcionalidades. */
if( req.headers.get("content-type")?.match('form-data') ){
const body = {}
const form = await req.clone().formData()
form.forEach((key, value)=>{
body[key] = value
})
}
else if(req.headers.get('content-type')?.match('application/json')){
const body = await req.clone().json()
}
body.id = products.length + 1
/* Almacenamos el producto en nuesta lista. */
products.push( body );
db.setItem("products", JSON.stringify( products) );
res.send({
data: body
});
/*Tip: Podríamos utilizar next("Guardado", 200); */
});
- Nuestro router ahora tiene un bridge en las rutas /products siempre que sean POST.
- Estamos utilizando localStorage como nuestro administrador de Base de Datos.
- Debido a que nuestra librería no modifica el cuerpo de la solicitud ni sus cabeceras de forma atomatica, es necesario modificarla manualmente.
- Generamos un ID en base a la cantidad de productos que se tienen almacenados e incluimos el producto en nuestra lista de productos.
- Guardamos la lista en la "base de datos"
- Resolvemos la solicitud al cliente con un cuerpo { data:(...) } y un Codigo HTTP de clase 200 - Success.
Perfecto, hasta ahora hemos aprendido a interceptar las solicitudes y procesarlas. Pero... ¿De que sirve procesar solicitudes que no son enviadas?, vamos a enviar algunas solicitudes a nuestro Bridge.
router.fetch("/products",{
method:"POST",
body: JSON.stringfy({
price: 1260.15,
title:"Smart Phone",
description: "Gold Edition",
}),
})
.then(async res=>{
if( res.ok ) return res.json(); // Convertimos la respuesta a formato JSON
throw new Error( await res.text() ); // Enviamos un error en caso de existir alguno.
})
.then(response=>{
if( response.data ) alert("El producto fué almacenado.");
else alert("Ups! Tuvimos un problema al almacenar el producto.");
})
.catch(err=> alert( err.message ))
- Realizaos una solicitud a nuestro router, como cualquier solicitud Fetch.
- Cargamos la informacion de nuestro producto.
- Analizamos la respuesta recibida y la convertimos a JSON en caso de ser posible.
- Si el producto se almacenó, mostramos una alerta en el navegador.
Estos son solo algunos de los posibles usos de la librería, en breve estaremos anexando más ejemplos de las funcionalidades y los alcances de la librería.
¿Want to discuss any of my open source projects, or something else?Send me a direct message on Twitter. If you already use these libraries and want to support us to continue development, you can sponsor us at Github Sponsors.