Introducing “Enlaces interesantes”, y cómo acceder al RSS/ATOM de Facebook desde .NET

Llevo ya algún tiempo utilizando la página de Variable Not Found en Facebook para publicar enlaces interesantes sobre desarrollo, ASP.NET, MVC y otros temas que voy encontrando por ahí. Normalmente anoto entradas en blogs, artículos o sitios webs a los que considero que vale la pena echar un vistazo en los ratos libres.

Integración Facebook-Twitter-BlogAdemás de en la página del blog en la red social, como por arte de magia, estos enlaces se difunden simultáneamente desde mi perfil personal de Facebook y a través de Twitter. Sin embargo, desde hace tiempo estaba estudiando la posibilidad de recopilar a su vez toda esta información para poder publicarla en el blog, cerrando completamente el círculo.

Aprovechando un huequito he creado una pequeña aplicación que toma esos enlaces y los maqueta de forma automática para mostrarlos en Variable not found. Así, a la vez que hago llegar estos enlaces a los suscriptores y lectores ocasionales del blog, los almaceno agrupados en una única ubicación sobre la que es posible realizar búsquedas, que es más cómodo que tomar rabos de pasas 😉

En un principio orienté la solución utilizando el SDK de Facebook (como introducción os recomiendo leer esta magnífica serie del amigo Eduard Tomás), pero estaba intentando matar mosquitos a cañonazos: demasiada complejidad para una necesidad tan simple.

Afortunadamente, me di cuenta de que esta información está disponible en formato ATOM y RSS, por lo que en principio puede ser consumida utilizando las clases de sindicación introducidas con .NET 3.5 en el espacio de nombres System.ServiceModel.Syndication del ensamblado System.ServiceModel.Web.

Por tanto, debería bastar con obtener las feeds, por ejemplo en formato ATOM, desde la dirección del feed http://www.facebook.com/feeds/page.php?format=atom10&id=94490426991, ¿no?

XmlException: Por razones de seguridad DTD está prohibido en este documento…

Pero claro, las cosas nunca son tan sencillas como se prevé en un principio. Utilizando contra los feeds de Facebook el código convencional para acceder a este tipo de información (y que de hecho funciona con muchos otros feeds), se lanzaba una excepción con un misterioso mensaje:

XmlReader reader = XmlReader.Create(feedURL);
SyndicationFeed feed = SyndicationFeed.Load(reader);
 
// Excepción XmlLException              ^^^^
//   "Por razones de seguridad DTD está prohibido en este documento XML. 
//    Para habilitar el procesamiento DTD establezca la propiedad ProhibitDtd 
//    en XmlReaderSettings como false y pásela al método XmlReader.Create."

Gracias a la inestimable colaboración del compañero Fiddler, pude averiguar que el problema se debía a que Facebook no estaba retornando la información en el formato solicitado (en este caso, ATOM), sino HTML:

Capturando tráfico con Fiddler

Si observáis, la petición inicial es redirigida a un nuevo recurso mediante un código de respuesta 302, una página web en cuyo título podemos observar el texto “Navegador incompatible”.

El motivo es que, obviamente, la petición realizada automáticamente por XmlReader para obtener los datos no incluye información sobre el navegador utilizado, Facebook detecta esta circunstancia y nos devuelve una página como la siguiente:

Estoy utilizando un navegador no compatible

Y esa es precisamente la causa de la excepción: los datos retornados no se encuentran en el formato esperado.

Para cambiar esto es necesario modificar ligeramente el código anterior, creando de forma manual la petición HTTP e inyectándole en el encabezado User-Agent un valor reconocible por los servidores de Facebook, como “Mozilla/4.0”, el empleado por IE8.

Para crear el objeto XmlReader utilizamos otra sobrecarga, de forma que le suministramos el Stream de respuesta de la conexión que hemos creado:

HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(feedURL);
wr.UserAgent = "Mozilla/4.0";
 
XmlReader reader = XmlReader.Create(
   wr.GetResponse().GetResponseStream()
);
 
SyndicationFeed feed = SyndicationFeed.Load(reader);
foreach (var item in feed.Items)
{
   // Procesar entrada...

De esta forma, podemos acceder a feeds, incluso a los de Facebook, para obtener información y procesarla a nuestro antojo.

En el caso de mi megasuperaplicación, simplemente he tenido que parsear un poco el contenido y generar marcado HTML para cada entrada del feed con objeto de conseguir algo parecido a lo siguiente:

Aspecto de enlaces en Variable Not Found

El resultado lo podéis ver desde hace unas semanas en http://www.variablenotfound.com/search/label/enlaces.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *