Servidor HTTP con Deno 💻
Me monto un servidor HTTP básico con Deno porque he perdido varias horas para conseguir un servidor HTTP que me acepte peticiones POST y no lo he conseguido ni con ChatGPT ni con StackOverflow.
Todo lo que encontraba estaba deprecated.
A continuación el código que sí funcione a día de hoy 👇
Librerías
Las librerías las puedes hardcodear en el fichero principal o bien sacarlas a un fichero deps.ts o con el nombre que quieras para que sólo haya un fichero fuente con las librerías.
Aunque podría hacerlo todo en el mismo fichero, lo separaré para mi yo del futuro 😉
//deps.ts export { Application,Router } from "https://deno.land/x/oak@v10.6.0/mod.ts"; export type { RouterContext } from "https://deno.land/x/oak@v10.6.0/mod.ts";
❗❗ Recuerda incluir la librería https://deno.land/x/dotenv@v3.2.0/load.ts en el fichero donde quieras cargar las variables de entorno.
En el fichero donde quieras añadir librerías lo que haces es importar de tu fichero de librerías, en mi caso deps.ts.
// en el fichero que quieras usar alguna librería import { Application, Router } from "./deps.ts";
La aplicación
//main.ts import { Application, Router } from "./deps.ts"; //🔥 Para leer las variables de entorno 👇 import "https://deno.land/x/dotenv@v3.2.0/load.ts"; const app = new Application(); const router = new Router(); // petición GET a "/api/holaMundo" router.get("/api/holaMundo", (ctx) => { ctx.response.body = "Hola mundo❗"; ctx.response.status = 201; }); // petición POST a "/api/holaMundo" router.post("/api/holaMundo", async (ctx) => { const contentLengthHeader=ctx.request.headers.get("content-length") || 0; const contentType =ctx.request.headers.get("content-type") || false; if(!ctx.request.hasBody || contentLengthHeader===0 || !contentType){ ctx.response.body = "No se han enviado días para reservar en el body de la petición"; ctx.response.status = 400; return; } const result = ctx.request.body(); // content type automatically detected if (result.type === "json") { const value = await result.value; // an object of parsed JSON console.log(value); } ctx.response.body = "Hola mundo❗"; ctx.response.status = 200; }); // añade las rutas al servidor app.use(router.routes()); app.use(router.allowedMethods()); console.log('Servidor HTTP en puerto $/{PORT}/'); await app.listen({ port: PORT });
Los endpoint
Petición GET
router.get("/api/holaMundo", (ctx) => { ctx.response.body = "Hola mundo❗"; ctx.response.status = 201; });
Si ejecutas el servidor HTTP y le haces una petición GET a http://localhost:8080/api/holamundo te debe devolver lo siguiente:
Petición POST
router.post("/api/holaMundo", async (ctx) => { const contentLengthHeader=ctx.request.headers.get("content-length") || 0; const contentType =ctx.request.headers.get("content-type") || false; if(!ctx.request.hasBody || contentLengthHeader===0 || !contentType){ ctx.response.body = "No se han enviado días para reservar en el body de la petición"; ctx.response.status = 400; return; } const result = ctx.request.body(); // content type automatically detected if (result.type === "json") { const value = await result.value; // an object of parsed JSON console.log(value); } ctx.response.body = "Hola mundo❗"; ctx.response.status = 200; });
Si ejecutas el servidor HTTP y le haces una petición POST a http://localhost:8080/api/holamundo sin body te debe devolver lo siguiente:
Si añades un body con formato JSON te debe de responder lo siguiente:
¿Cómo dejar a Deno que escoja un puerto libre al levantar la aplicación?
En ocasiones, puede que si especificas un puerto por el cuál tu servidor HTTP escuche éste esté ocupado por lo que tu aplicación no levantará.
Si no quieres especificar un puerto, ni por variables de entorno ni por ningún otro método, antes de poner al servidor a escuchar, creamos un listener que devolverá el puerto cuando el servidor HTTP haya iniciado
app.use(router.routes()); app.use(router.allowedMethods()); app.addEventListener('listen', ({port}) => { console.log(`Escuchando en el puerto ${port}`); }); await app.listen();
Disfrútalo 😉
Hasta luego 🖖