El otro día estaba buscando algo tipo «Serverless» que pudiera anexar a mi servidor (¿qué irónico no?) pero más que nada mi idea era poder generar endpoints simples que pudiera generar sin tener que estar montando nada y modificando cosas en Express por ejemplo para nuevas rutas, o cosas por el estilo y solo fuera algo tipo «https://mi-empresa.com/api/mi-endpoint» y que «mi-endpoint» fuera un archivo que respondiera…
Lamentablemente no encontré algo que se adaptara a mi necesidad tan simple, y aún más porque tengo un servidor Plesk en el cual pues era estar picando «Actualizar» cada vez que le agregara algo ya que no quería ni generar repositorios porque en este caso la API era algo super simple con endpoints super simples, que solo reciben un dato y hacen X cosa, reciben Y y hacen Y, cosas así…. así que bueno me decidí a hacer algo simple que me permitiera hacer lo que quiero, eso sí como dice el título es algo super simple, por lo que podremos extenderlo pero eso ya será por si genero un repo para esto y compartirlo e ir extendiendo la funcionalidad.
Lo primero que necesitamos es generar un nuevo proyecto, para ello podemos utilizar npm init -y y vamos a instalar 1 sola dependencia, npm install fastify y es todo lo que ocupamos.
Ya que tengamos el proyecto, vamos a generar un archivo index.js, con el siguiente código:
const fastify = require('fastify')({ logger: true });
const path = require('path');
const fs = require('fs');
const SECRET_TOKEN = '';
fastify.all('/api/:functionName', async (request, response) => {
const authHeader = request.headers['authorization'];
if (!authHeader || !authHeader.toLowerCase().startsWith('bearer ')) {
return response.code(401).send({
message: "Token required",
error: "unauthorized",
statusCode: 401
});
}
const token = authHeader.split(' ')[1];
if (token !== SECRET_TOKEN) {
return response.code(403).send({
message: "Invalid token",
error: "forbidden",
statusCode: 403
});
}
const { functionName } = request.params;
const filePath = path.join(__dirname, 'functions', `${functionName}.js`);
if (!fs.existsSync(filePath)) {
return response.code(404).send({
message: "Resource not found",
error: "not-found",
statusCode: 404
});
}
try {
delete require.cache[require.resolve(filePath)];
const handler = require(filePath);
return await handler(request, response);
} catch (error) {
return response.code(500).send({
message: `Server error ${error.toString()}`,
error: "index-server-error",
statusCode: 500
});
}
});
fastify.listen({ port: 3000, host: '0.0.0.0' });
Vamos por partes, lo primero es que yo agrego una verificación para autenticarse usando una token, ¿es necesario? claro que no, pero esto protegerá todos los endpoints en caso de que alguien intente hacer mal uso de ellos, puedes borrarlo si lo deseas de la línea 7 a la 22 y es todo.
Ahora, aquí viene la magia, lo que hace es que leemos los archivos, si no existe pues «404» claro está, pero si existe, lo quitamos de un caché existente y lo cargamos tal como viene, así siempre estaremos leyendo el archivo actualizado por cada petición.
En caso de que algo esté mal en el archivo, vamos a retornar un error.
Por último inicializamos fastify para cualquier IP en el puerto 3000, esto claro, tú lo puedes modificar, si lo quieres ejecutar en el 80, agregarle certificados o demás (pero esto como digo es cosa de «si decido crecerlo y ponerlo más público»)
Ya casi terminamos, ahora solo crea un directorio llamado functions, dentro crea por ejemplo un archivo llamado hello-world.js el nombre del archivo será el nombre del endpoint (incluso podemos extender aún más y agregar versionados pero otra vez, para otra ocasión)… entonces este archivo responderá a la siguiente URL:
https://mi-empresa.com/api/hello-worldPero, ¿cómo lo hace?, bueno para ello al contenido vamos a ponerle lo siguiente:
module.exports = async (request, response) => {
return {
status: "success",
message: "Hello world from my function!",
meta: {
server_time: new Date()
}
};
};Básicamente tenemos 2 parámetros, un request (la petición en caso de por ejemplo tener peticiones POST, y un response, para enviar códigos de estado específicos)… en este caso, responde con un GET, pero, ¿qué tal si como digo quiero un POST?, ¡Fácil! (¡Gracias Fastify por todo esto!), solo agrega esto hasta arriba (debajo claro del module.exports... => {)
if (request.method !== 'POST') {
return response.code(405).send({
message: "Method not allowed",
error: "method-not-allowed",
});
}Con esto puedes controlar que solo puedas recibir POST… también nota que agregué que ahora responda con response.code(...).send(...) esto nos permite responder con un statusCode como mencionaba. Y por último, ¿cómo leo entonces la petición?, otra vez, fácil (¡Gracias Fastify x2!):
const { message } = request.body ?? {};Tan simple como hacer esto donde a la izquierda generamos las variables del objeto de body, o si eres más del clásico:
const body = request.body ?? {}
body.message; // lo mismo que arribaY pues ya tu puedes validar, como if(!message) { /* mandar error */ } etc… súper fácil.
Y eso fue todo, para la próxima si decido hacerlo a modo repo planeo que aún sea más fácil para por ejemplo response con el status code sea con algún método, wrappear la posibilidad de agregar autenticación del bearer o no con una configuración, permitir bloquear el recurso de forma más fácil, agregar versionado, etc. PERO siempre manteniendo la simplicidad de todo esto y no irnos a un proyecto sobre-complicado para hacer cosas básicas…
Nos vemos en el próximo tutorial, espero te haya gustado y no te olvides de suscri… espera esto no es YouTube, bueno de quitar el Adblock, o rolarme para un café en PayPal si te sirvió esto… ¡Suerte!






