Node.js y Express: Rutas Avanzadas

Publicado el 04 noviembre 2013 por Codehero @codeheroblog

Múltiples Parámetros por Segmento de URL

Supongamos que tenemos un array de nombres de personas:

var authors = ["Alberto", "Carlos", "Jonathan", "Oscar", "Ramses", "Ricardo"];

1 varauthors=["Alberto","Carlos","Jonathan","Oscar","Ramses","Ricardo"];

Pudiéramos pedir los autores que están comprendidos en un rango según su posición en el Array:

app.get('/authors/:from-:to', function (request, response) { var from = parseInt(request.params.from, 10), to = parseInt(request.params.to, 10); response.json(authors.slice(from, to + 1)); });

12345678 appget('/authors/:from-:to',function(request,response){    varfrom=parseInt(requestparamsfrom,10),   to   =parseInt(requestparamsto,10);    responsejson(authorsslice(from,to+1));  });

En este bloque de código obtuve dos parámetros que están en un mismo segmento de url y los convertí a entero. Luego retorné como json el rango requerido del array de autores.


Parámetros Pre-Condicionados

Los parámetros pre-condicionados tienen que ver con el middleware. Mediante este método podemos obtener los parámetros antes de que lleguen a nuestros controladores de ruta para hacerle algún tipo de modificación.

Tomando la misma idea del ejemplo anterior creamos dos métodos de middleware, uno para cada parámetro.

app.param('from', function (request, response, next, from) { request.from = parseInt(from, 10); next(); });

123456 appparam('from',function(request,response,next,from){   requestfrom=parseInt(from,10);  next(); });

Con este método convertimos el parámetro “from” a entero antes de llegar al método de la ruta. “Next” viene siendo una función de middleware que debe ser llamada siempre al final, esta indica que se puede continuar al siguiente middleware de la lista que se configura al inicio de la aplicación.

Ahora continuamos con el método para el parámetro “to”.

app.param('to', function (request, response, next, to) { request.to = parseInt(to, 10); next(); });

123456 appparam('to',function(request,response,next,to){   requestto=parseInt(to,10);  next(); });

Y ahora en la función de nuestra ruta solo tenemos que hacer lo siguiente:

app.get('/authors/:from-:to', function (request, response) { response.json(authors.slice(request.from, request.to + 1)); });

12345 appget('/authors/:from-:to',function(request,response){    responsejson(authorsslice(requestfrom,requestto+1));  });

Con esto logramos el mismo resultado que en el ejemplo anterior, solo que escribimos más código. Puede parecer absurdo en este momento, pero si tu aplicación necesitara recibir estos parámetros en múltiples rutas, ahorra tiempo que tener que repetir la conversión a entero en cada ruta. También podría ser útil si se necesitara de algún tipo de autenticación, o extraer información de una base de datos, etc.


Sobre escritura de rutas

si vamos a la configuración de nuestra aplicación vemos que hay un montón de middleware:

app.set('port', process.env.PORT || 3000); app.set('views', __dirname + '/views'); app.set('view engine', 'jade'); app.use(express.favicon()); app.use(express.logger('dev')); app.use( express.cookieParser() ); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(path.join(__dirname, 'public')));

12345678910 appset('port',processenvPORT||3000);appset('views',__dirname+'/views');appset('view engine','jade');appuse(expressfavicon());appuse(expresslogger('dev'));appuse(expresscookieParser());appuse(expressbodyParser());appuse(expressmethodOverride());appuse(approuter);appuse(expressstatic(pathjoin(__dirname,'public')));

Tengo particular interés en que nos fijemos en la última línea del código:

app.use(express.static(path.join(__dirname, 'public')));

1 appuse(expressstatic(pathjoin(__dirname,'public')));

Esta línea indica que los archivos que estén en la carpeta “/public” son estáticos. Esto quiere decir que si tenemos un archivo llamado “download.zip” en esa carpeta y vamos a la dirección “localhost:3000/download.zip” el archivo se descargará del servidor a nuestra carpeta de descargas.

Vamos a suponer que yo quiero contar el numero de veces que ha sigo descargado el archivo. Mediante una variable llamada “count”, que no vamos a guardar en ninguna parte, solo en memoria (si se apaga el servidor se borra este valor), vamos a guardar la cantidad de veces que se descargó el archivo.

var count = 0;

1 varcount=0;

Creamos la variable en cualquier parte de app.js, antes de la ruta que vamos a crear:

app.get('/download.zip', function (request, response, next) { count++; next(); });

123456 appget('/download.zip',function(request,response,next){   count++;  next(); });

En este caso pasamos la función next a la ruta porque no vamos a retornar con un “response”, entonces llamamos a next() al final de la función para que continue la ejecución con el siguiente paso.

Ahora si quisiéramos saber cuantas veces se ha descargado el archivo, podemos crear una ruta para solicitar el valor de la variable count.

app.get('/count', function (request, response) { request.send("" + count + " descargas"); });

12345 appget('/count',function(request,response){   requestsend(""+count+" descargas"); });

Claro que si no queremos perder el valor de count cuando apaguemos el servidor, tenemos que guardarlo en una base de datos.


Sobrecarga de rutas

Cuando hemos escrito el código que se encarga de manejar una ruta, siempre lo hemos hecho pasando una función. Resulta que se pueden pasar múltiples funciones que serán ejecutadas en el orden en que fueron pasadas a la ruta.

Tomando el array del primer ejemplo vamos a crear una función que retorne el autor de la posición solicitada:

function userAtIndex (request, response, next) { request.author = authors[parseInt(request.params.authorId, 10)]; next(); });

1234 functionuserAtIndex(request,response,next){  requestauthor=authors[parseInt(requestparamsauthorId,10)];  next();});

Es importante llamar a next() para que la aplicación continue la ejecución hacia la próxima función.

Ahora, en la ruta pasamos como parámetro a la función userAtIndex:

app.get("/users/:authorId", userAtIndex, function (request, response) { response.json(request.author); });

123 appget("/users/:authorId",userAtIndex,function(request,response){  responsejson(requestauthor);});


Conclusión

En este tutorial hemos aprendido algunas técnicas avanzadas sobre el manejo de rutas en Node.js con Express.

Espero que haya servido de ayuda esta información. Ya sabes que puedes dejar tus dudas o comentarios en la sección correspondiente que está más abajo en esta página.

Ya será hasta un próximo tutorial de Node.js y Express.

Hasta pronto.