Rutas en Hapijs (II)

Las rutas en hapijs tienen varias opciones al momento de definirse, según lo que he leído en su documentación y lo aplicado en un API que estoy creando a modo de prueba y aprendizaje voy a explicar dichas opciones.

Method

Una ruta debe tener un método que representa un verbo HTTP, puede ser asignado via una cadena o como un array de cadenas.

var singleMethodRoute = {

    method: 'GET'

};

var multipleMethodRoute = {

    method: ['GET','POST']

};
Path

El path se usará para definir el url de una ruta, en este caso solo puede ser definido como un string, puede tener parámetros que deben ser definidos entre llaves "{}" y por defectos son obligatorios, pero existe una manera de definirlos como opcionales.

var route = {

    method: 'GET',

    path: '/products/{id}', //parámetro id obligatorio

    handler: function (request, reply) {

        var productId = request.params.id;

    }    

};

Ya que definimos el parámetro entre llaves con el nombre id para acceder a su valor en el código también debemos usar el mismo nombre.

Path con parámetros opcionales

En el ejemplo anterior si se hace un request a la ruta /products/1 o /products/2 funcionaría sin problemas, pero /products retornaría un error 404. Si nos encontramos en esta situación podemos definir el parámetro como opcional usando el signo de interrogación al final del parámetro. Ojo que siempre entre llaves. La siguiente ruta funcionará indiquemos o no un id, la forma de acceder al valor del parámetro no cambia, igual debemos usar request.params.id. Solo que debemos tener en cuenta que ahora id puede ser núlo.

var route = {

    method: 'POST',

    path: '/products/{id?}'

};
Handler

La propiedad handler es una función que recibe dos parámetros request y reply. Request tiene toda la información del cliente tal como datos enviados, parámetros del url, autenticación, headers, para ver todas las propiedades de este objeto leer la documentación asociada.

Reply es el método usado para responder la petición al cliente, reply acepta como parámetro la data que se desea enviar al cliente.

var route = {

    method: 'GET',

    path: '/products/{id}', //parámetro id obligatorio

    handler: function (request, reply) {

        var productId = request.params.id;

        reply({newId: productId}); //uso básico de reply

    }    

};

Pero en la mayoría de casos vamos a realizar alguna operación asíncrona antes de hacer el llamado a reply para eso podemos beneficiarnos del método hold y asignamos el resultado a una variable que modificaremos según la respuesta de un método asíncrono.

handler: function (request, reply) {

    var productId = request.params.id;

    var response = reply().hold(); //mantenemos la respuesta en espera

    obtenerProducto(productId, function (err, productDetails) {

        if (err) {
            //si hay error cambiamos el status code a 500
            response.statusCode = 500;

        }
        else {
            //Si no hay error enviamos los datos al cliente
            response.source = productDetails;        
        }

        response.send();

    }); 

} 

Tenemos el método obtenerProducto que simula una conexión a una base de datos y devuelve los detalles de un producto según el ID.
Si ocurre un error cambiamos el status code a 500 para indicar al cliente que algo salió mal.
Si todo salió bien asignamos la información del producto a la propiedad source para que el cliente pueda hacer algo con esa información. En este escenario no necesitamos indicar un status code ya que por defecto es 200 que indica que todo salió bien.
Por último e independientemente de si existe un error o no enviamos la respuesta al cliente usando el método send.

Toda esta información puede ser encontrada en la documentación del framework.
Existen otras opciones para una ruta que permiten configurar autenticación, validación, caching, etc. Pero son temas más complejos y lo cubriré en un siguiente artículo.