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?

o inicia sesi贸n.

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