Servidor HTTP con Deno 💻

Publicado el 26.03.2023 a las 21:25

Servidor HTTP con Deno 💻

  1. Librerías

  2. El fichero principal del servidor HTTP

  3. Los endpoint

    • Petición GET

    • Petición POST

  4. ¿Cómo dejar a Deno que escoja un puerto libre al levantar la aplicación?

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 get a servidor HTTP desarrolado con Deno

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:

Respuesta de servidor HTTP a petición POST sin body

Si añades un body con formato JSON te debe de responder lo siguiente:

Respuesta de servidor HTTP a petición POST con body

¿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 🖖