Si tenemos un blog, es fundamental disponer de un canal RSS o Atom para que, por una parte, los usuarios pueden suscribirse a nuestra web y, por otra parte, los agregadores de noticias tengan acceso a nuestro contenido, lo que nos traerá más visitas. Vamos a ver como generar este típo de canal con NodeJS, Express, Mongoose y MongoDB


En este artículo se supone que el lector está familiarizado con NodeJS+Express. Por lo tanto vamos a ir directos a los archivos que necesitamos para publicar nuestro feed. En este artículo se presenta el código para generar el feed de este blog: http://www.iteracion42.com/feed/.

Esquema documentos MongoDB y lectura de datos

Primero que nada vamos a ver como almacenamos los posts de nuestro blog. En el archivo posts.js tendremos el esquema del documento MongoDB, que sería el siguiente:

var mongoose     = require('mongoose');
var Schema       = mongoose.Schema;

var PostSchema = new Schema({
    _id: Number,
    title: String,
    body: String,
    published_at: Date,
    canonical: String,
    author: String
});

module.exports = mongoose.model('Post', PostSchema);
Dentro del direcotrio routes, creamos el archivo feed.js:
var express = require('express');
var router  = express.Router();

var Post    = require('../models/post');

/* GET home page. */
router.get('/', function(req, res, next) {

  Post.find({ }).sort({ published_at: -1} ).exec(function (error, db_posts) {
      if(error) { console.log(error) }

        db_posts.forEach( function (post, index) {
            db_posts[index].body = post.body.split('<hr>')[0];
            db_posts[index].body = post.body.replace('<p>','').replace('</p>','');
            });

        res.setHeader('content-type', 'application/rss+xml');

        res.render('feed', {
            pretty: true,
         title: 'Iteración 42',
         description: 'Un poco de programación y un algo sobre sistemas',
         posts: db_posts
      });
  });

});


module.exports = router;

Aquí hay que tener en cuenta 2 cosas. La primera es la línea "res.setHeader('content-type', 'application/rss+xml');". Un archivo RSS no es plain/text y, aunque muchos lectores ignoran este error, no es correcto publicarlo con el header incorrecto. Otro punto a tener en cuenta es: "pretty: true,". Con esto obligamos a Express a renderizar el html con saltos de línea. Al estándar RSS no le gusta el código en una sola línea. Con algunos agregadores de noticias se puede tener problemas.

Generar el feed con Jade

A continuación el código para la plantilla Jade de nuesto Feed RSS:

doctype xml
rss(version='2.0', xmlns:atom='http://www.w3.org/2005/Atom')
    channel
        title #{title}
        link http://www.iteracion42.com
        description #{description}
        language es-ES
        copyright Copyright 2016, Iteración 42
        generator Iteración 42
        if posts.length
            lastBuildDate= new Date(posts[0].published_at).toUTCString()
        |
        | <atom:link href="http://www.iteracion42.com/feed/" rel="self" type="application/rss+xml"/>

        each post in posts
            item
                title= post.title
                link http://www.iteracion42.com/viewpost/#{post.id}/#{post.canonical}
                guid http://www.iteracion42.com/viewpost/#{post.id}/#{post.canonical}
                description #{post.body}
                pubDate= new Date(post.published_at).toUTCString()

La línea más extraña puede ser donde declaramos el atom:link que, pese a no ser necesaria para cumplir el estándar RSS 2.0, el comprobador de RSS lo marcaba como error. De esta forma me aseguro que este feed será compatible con el 100% de agregadores de noticias. En los items, tenemos por ducplicado link e guid. Otra vez, es para asegurar la compatibilidad con todos los agregadores de noticias.

Para comprobar el feed se han utilizado los comprobadores: https://validator.w3.org/feed/ y http://www.feedvalidator.org/.