Introducción

1

Qué necesitas para este curso y qué aprenderás sobre Node.js con Hapi

2

Conceptos principales de hapi y creación de nuestro primer servidor

3

Breve historia y estado actual

Creando un sitio básico con Hapi

4

El objeto h, response y sus herramientas

5

Uso de plugins - Contenido estático

6

Plantillas con Handlebars

7

Renderizado de vistas - Layout y template del home

8

Recibiendo parámetros en una ruta POST - Creación del registro

9

Definir una mejor estructura con buenas prácticas en Hapi

10

Validando la información - Implementando Joi

11

Introducción a Firebase

12

Creando un modelo y guardando en firebase

13

Implementando el login y validación del usuario

14

Autenticación de usuarios - Cookies y estado

15

Manejando errores

16

Visualización de errores

17

Controlar el error 404 en inert y el error de validación

18

Repaso - Creación del modelo y controlador para preguntas

19

Repaso - Creación de las rutas para crear preguntas

20

Listar las últimas preguntas en el home

Aplicacion de conceptos avanzados

21

Enrutamiento avanzado - visualizando una pregunta

22

Enrutamiento avanzado - respondiendo una pregunta

23

Generando la lógica de la plantilla según si es creador o contribuidor

24

Métodos de servidor - respuesta correcta

25

Usando métodos de servidor

26

Manejo del caché - Agregando el home al caché

27

Procesamiento de archivos - Aceptando imágenes

28

Logging con Good - Monitoreando el servidor

29

Creación de plugins - Teoría

30

Creación de plugins - Implementando un API REST

31

Estrategías de autenticación - Asegurando el API REST

32

Seguridad básica - Asegurando el servidor contra CSRF

33

Seguridad básica - Asegurando el servidor contra XSS

Herramientas de desarrollo

34

Depuración del proyecto

35

Ecosistema de Hapi

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Definir una mejor estructura con buenas prácticas en Hapi

9/35
Recursos

Con el fin de tener una mejor organización de los archivos de nuestro proyecto, y considerando que estamos trabajando con la arquitectura MVC, haremos una primera refactorización del código.

Creamos el directorio /controllers para colocar los controladores site y user de nuestro proyecto. Pasamos la definición de las rutas a su propio módulo routes.js como un arreglo que exportaremos más adelante. Distribuímos los handlers asociados a cada vista en la definición de las rutas hacia el archivo del controlador para cada contexto, ya sea site o user. Requerimos los controladores desde el módulo de rutas, y fnalmente importamos la definición de rutas desde el index.js y las asociamos al server con server.route(routes).

La raíz de la estructura general quedaría de momento:
-/public
-/controllers
-/views
-routers.js
-index.js

Aportes 9

Preguntas 3

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Mi aporte en el código
Archivo index.js

'use strict'

// Requerir el modulo de hapi (Framework)
const Hapi = require('@hapi/hapi')
// Requerir el plugin de hapi para servir archivos estaticos
const inert = require('@hapi/inert')
// Requerir el plugin de hapi para gestionar el motor de plantillas
const vision = require('@hapi/vision')
const path = require('path')

// Requerir archivo de rutas
const routes = require('./router')

// Configurar el servidor de nuestra aplicación. En un contenedor (Docker) si marca error colocar 0.0.0.0 (todos)
const server = Hapi.server({
  port: process.env.PORT || 3000,
  host: 'localhost',
  // Definir propiedades generales para todas las rutas. (En este caso indico que las rutas que requieran archivos estáticos, se servirán desde la carpeta public)
  routes: {
    files: {
      relativeTo: path.join(__dirname, 'public')
    }
  }

})

// Definicion de función para inicializar el proyecto. Intenamnete hay tareas asincronas
async function init() {

  try {
    // Registrar plugins de hapi para servir archivos estaticos
    await server.register(inert)
    // Registrar plugin para gestionar el motor de plantillas
    await server.register(vision)

    // Configurar nuestro motor de plantillas.
    server.views({
      engines: {
        hbs: require('handlebars')
      },
      relativeTo: __dirname,
      path: 'views',
      layout: true,
      layoutPath: 'layouts'
    })

    // Registrar archivo de rutas en la aplicación
    server.route(routes)
    // Arrancar el servidor de Hapi
    await server.start()
    console.log(`Servidor lanzado en: ${server.info.uri}`)
  } catch (error) {
    console.error(error)
    // Salir de nodeJS con un código de error (1), 0 es un código de exito
    process.exit(1)
  }
}

// Inicializar el proyecto
init();

Archivo router.js

// Requerir modulos de controlador de ruta
const siteController = require('./controllers/site')
const userController = require('./controllers/user')

// Declarar conjunto de rutas y asociar su respectivo controlador de ruta
const routes = [
  {
    method: 'GET',
    path: '/',
    handler: siteController.index
  },
  {
    method: 'GET',
    path: '/register',
    handler: userController.register
  },
  {
    method: 'POST',
    path: '/create-user',
    handler: userController.createUser
  },
  {
    // Ruta para servir archivos estáticos asociados (img/css/js)
    method: 'GET',
    path: '/{param*}',
    handler: {
      directory: {
        path: '.',
        redirectToSlash: true
      }
    }
  }
];

module.exports = routes

Archivo userController.js

// Definición de controladores de ruta

function register(req, h) {
  return h.view('register')
}

function createUser(req, h) {
  console.log(req.payload)
  return 'Usuario creado satisfactoriamente'
}

module.exports = {
  register,
  createUser
}

Archivo siteController.js

// Definición de controlaadores de ruta

function index(req, h) {
  return h.view('index', {
    title: 'Home'
  })
}

module.exports = {
  index
}

'use strict'

// Requerir el modulo de hapi (Framework)
const Hapi = require('@hapi/hapi')
const handlerbars = require('handlebars') // para implementacion de plantillas
const inert = require('inert') // extiende los metodos disponible en el objeto h
const vision = require('@hapi/vision') //para implementar el uso de vistas. Hay que configurarlo por ser un plugin
const path = require('path') // nos permite definir una ubicación relativa para todos los routes de nuestro proyecto
const routes = require('./routes')

// Configurar el servidor de nuestra aplicación. En un contenedor (Docker) si marca error colocar 0.0.0.0 (todos)
const server = Hapi.server({
    port: process.env.PORT || 3000,
    host: 'localhost',
    //definir desde donde va acceder a las rutas. relaviteTo (routes.files)
    routes: {
        files: {
            relativeTo: path.join(__dirname, 'public')
        }
    } 
})

// Definicion de función para inicializar el proyecto. Internamente hay tareas asincronas
async function init() {

  // Arrancar el servidor de HapiJS, se considera una tarea asincrona.
    try {
        // registrando inert
        await server.register(inert)
        //registrando vision
        await server.register(vision)
        //configuracion de vision
        server.views({
            engines: {  //hapi puede usar diferentes engines
                hbs: handlerbars //asociamos el plugin al tipo de archivo
            },
            relativeTo: __dirname, //para que las vistas las busque fuera de /public
            path: 'views', //directorio done colocaremos las vistas dento de nuestro proyecto
            layout: true, //indica que usaremos layouts
            layoutPath: 'views' //ubicacion de layouts
        })
        server.route(routes)
        await server.start()
    } catch (error) {
        console.error(error)
    // Salir de nodeJS con un código de error (1), 0 es un código de exito
        process.exit(1)
    }

    console.log(`Servidor lanzado en: ${server.info.uri}`)
}

// Inicializar el proyecto
init();
'use strict'

const Hapi = require('hapi')
const handlebars = require('handlebars')
const config = require('./config')
const inert = require('inert')
const path = require('path')
const routes = require('./routes')
const vision = require('vision')

const server = Hapi.server({
  port: config.port,
  host: config.host,
  routes: {
    files: {
      relativeTo: path.join(__dirname, 'public')
    }
  }
})

async function init () {
  try {
    await server.register(inert)
    await server.register(vision)

    server.views({
      engines: {
        hbs: handlebars
      },
      relativeTo: __dirname, 
      path: 'views',
      layout: true,
      layoutPath: 'views'
    })

    server.route(routes)

    await server.start()
  } catch (error) {
    console.error(error)
    process.exit(1)
  }

  console.log(`Servidor lanzado en: ${server.info.uri}`)
}

init()

👍👌

¡Hola a todos!

Continuando un poco con el primer release que comparti con la inclusión de typescript, les comparto esta implementación con Pug como view engine. Cualquier feedbakc es bienvenida y PR abiertas

release-0,2,view-engine

hapi-repo

import Hapi from '@hapi/hapi';
import inert from '@hapi/inert';
import vision from '@hapi/vision';
import path from 'path';
import pug from 'pug';
import router from '../routes';

const port = process.env.PORT || 3000;
const host = process.env.HOST || 'localhost';
const routes: Hapi.RouteOptions = {
  files: {
    relativeTo: path.join(__dirname, '..', 'public'),
  },
};

const init = async () => {
  const server = Hapi.server({ port, host, routes });

  await server.register(inert);
  await server.register(vision);

  server.views({
    engines: { pug },
    relativeTo: path.join(__dirname, '..'),
    path: 'views',
  });

  server.route(router);

  await server.start();
  console.log(`Server online on port: ${server.info.port}`);
};

export { init };


'use strict'

const Hapi = require('hapi')//framework
const handlerbars = require('handlebars')// motor de platillas
const inert =  require('inert')//plugin
const path = require('path')//modulo nativo de Node
const routes = require('./routes')
const vision = require('vision')// plugin para getionar el motor de plantillas

const server = Hapi.server({
    port: 3000,
    host: 'localhost',
    routes: {
        files:{
            //ponemos que para todas las rutas que este sera el directorio de staticos
            relativeTo: path.join(__dirname, 'public')
        }
    }
})

async function init () {
    try {
        //Le debemos indicar a hapi que usaremos este plugin, no basta con requerirlo
        await server.register(inert)
        await server.register(vision)
        server.views({
            // define que tipo de motor de platillas vamos a usar, vision soporta diferentes motores de platillas
            engines:{
                hbs: handlerbars
            },
            relativeTo: __dirname,
            path: 'views',
            layout: true,
            layoutPath: 'views'
        })
        server.route(routes)
        //arrancar el servidor de HapiJS se considera tarea asincrona
        await server.start()
    }
    catch (error) {
        console.error(error);
        process.exit(1)
        //Salir de Node con un codigo de errir (1), 0 es un codigo de exito
    }
    console.log(`Servidor lanzado en: ${server.info.uri}`);
}
//Inicializa el proyecto
init()

Ahora entiendo más el código del proyecto… Gracias MVC