Introducción a node.js y express
routing
El enrutamiento se refiere a cómo una aplicación express responde a las solicitudes de los clientes. Se utilizan los métodos de la aplicación app.METHOD y app.use que además del path al que responden, especifican una o varias funciones de callback que se ejecutan cada vez que se recibe una solicitud para el path indicado. Si se especifican varias funciones de callback se deben ejecutar las funciones next para que la ejecución pase a la siguiente, como ya se ha visto anteriormente.
Los paths incluidos como primer argumento en los métodos de ruta pueden ser cadenas, patrones de cadenas o expresiones regulares.
En los patrones de cadena se pueden utilizar los siguientes caracteres comodín:
- * coincide con cualquier cadena de cualquier longitud incluso cadena nula
- + coincide con cualquier cadena de longitud 1 en adelante
- ? coincide con el carácter o grupo, si está rodeado de paréntesis, o con cadena nula
Por ejemplo:
app.get('/ab*cd', function (req, res) { console.log(“sirve a path /abcd, a /abdsscd o a /abs34asdacd”); }) app.get('/ab+cd', function (req, res) { console.log(“no sirve a path /abcd pero si a /abdsscd o a /abs34asdacd”); }) app.get('/ab?cd', function (req, res) { console.log(“sirve a path /abcd, a /acd pero no sirve a /abdsscd o a /abs34asdacd”); }) app.get('/ab(sx)?cd', function (req, res) { console.log(“sirve a path /abcd, a /absxcd pero no a /absxasdacd”); })
En los path de ruta se pueden especificar lo que se denominan parámetros de ruta. Con un ejemplo se ve mejor: Si el path en un método app.get es /datos/:usuario/ficha/:libro, y la petición de un cliente fuera a la dirección /datos/pepe/ficha/quijote entonces en la función de callback tendríamos acceso al nombre del usuario a través de req.params.usuario, que sería pepe y al libro a través de req.params.libro que sería quijote. Los parámetros de ruta se incorporan al path precediendo el nombre del parámetro de dos puntos. Para tener más control sobre la cadena exacta que puede coincidir con un parámetro de ruta, se puede agregar una expresión regular entre paréntesis ():
app.get(“/datos/:id(\\d+)
Solo coincidiría con rutas en la que el id solo contuviera números.
Las funciones de callback pueden terminar enviando la respuesta al cliente, o pueden encadenarse con el siguiente middelware si terminan ejecutando la función next().
Los métodos del objeto response de la siguiente tabla envían una respuesta al cliente y terminan el ciclo de solicitud-respuesta. Si ninguno de estos métodos se llama desde la función de callback, ni se ejecuta la función next(), la solicitud del cliente quedará pendiente y en el navegador del cliente se mostrará el mensaje de error de tiempo excedido.
- res.download Solicita la descarga de un archivo.
- res.end Finaliza el proceso de respuesta.
- res.json Envía una respuesta JSON.
- res.jsonp Envía una respuesta JSON con soporte JSONP.
- res.redirect Redirigir una solicitud.
- res.render Renderiza una plantilla de vista.
- res.send Envía una respuesta de varios tipos.
- res.sendFile Envía un archivo como una secuencia de octetos.
- res.sendStatus Establece el código de estado de la respuesta y envía su representación de cadena como el cuerpo de la respuesta.
Podemos modularizar la respuesta a peticiones haciendo uso de la clase Router de la clase express.
Con un ejemplo se verá. Tengamos un archivo de módulo con nombre libros.js con el siguiente contenido:
const router = require("express").Router(); router.get('/', function(req, res) { res.send('Página home de libros') }) router.get('/about', function(req, res) { res.send('Acerca de libros') }) module.exports = router
Y en index.js hacemos uso de él.
const libros = require("./libros"); const app = require('express')(); app.get("/", (req, res, next) => { res.send("Home"); }); app.use("/libros", libros); // atenderá peticiones para /libros/ y para /libros/about app.use((req, res, next) => { res.send(404,"recurso no encontrado"); // termina }); app.listen(8080, () => { console.log('servidor funcionando en puerto 8080'); })
Hemos separado, modularizado, las peticiones para todas las rutas bajo /libros a un archivo separado. Esto hace el código más estructurado, más legible y más fácil de mantener.