IPFS, el futuro de la web descentralizada

Imagina la web sin servicios centralizados. Donde puedas acceder a un vídeo o a una galería de fotos y que no haya una única manera de acceder a contenido. Eso y mucho más es IPFS. IPFS son las siglas de InterPlanetary File System y se trata de una red descentralizada de intercambio de archivos. Nos puede recordar a BitTorrent y en efecto, una buena descripción para IPFS es Torrent 2.0. No obstante IPFS implementa bastantes mejoras sobre BitTorrent, mejoras que lo hacen más útil.

En un post próximo explicaré como podemos sacar partido a IPFS ahora mismo, pero antes vamos a ver algunos conceptos fundamentales de IPFS.

Siendo más técnicos, IPFS es una red P2P inspirada en BitTorrent, Git y Kademlia. El protocolo es una red de distribución de contenido (CDN) y define un sistema de archivos donde el identificador es el propio contenido (a través de su hash). En IPFS nada desaparece sino que se versiona.

Vamos a ver como usar IPFS desde la terminal. Existen varios clientes, en diferentes lenguajes, como js-ipfs (que tendrá mucha utilidad en aplicaciones web descentralizadas usando JavaScript), pero de momento el cliente más maduro es go-ipfs. Desde la web puedes descargarlo.

Iniciar IPFS

Una vez IPFS esté instalado hay que ejecutar lo siguiente:

La segunda opción es para centros de datos, ya que reduce el tráfico interno.

Este comando genera las claves RSA del nodo, necesarias para la comunicación con la red IPFS. Además se nos informa de nuestro ID de nodo. Para acceder a este ID en cualquier momento podemos escribir:

Iniciar el nodo IPFS

Para acceder al contenido IPFS necesitamos ejecutar un nodo. Este nodo se inicia con ipfs daemon. Una cosa importante es que por ejecutar el nodo no se va a descargar nada que no pidamos. IPFS es explícito, pero necesita estar activo.

Obtener archivos

Ahora vamos a descargar nuestros primeros archivos de la red IPFS.

Para obtener un archivo existen varias formas:

Podemos usar el comando cat de IPFS, que funciona de forma similar a cat de Unix.

Las URL de IPFS todavía no han sido definidas de forma definitiva pero de momento siguen el siguiente formato: /protocolo (omitible)/hash/fichero (si es una carpeta). Es el hash el que identifica el bloque de contenido y es lo que sirve para encontrar el contenido en la red IPFS. Internamente usa una DHT (Distributed Hash Table). IPFS no usa trackers como las primeras versiones de BitTorrent. En cambio usa una DHT basada en Kademlia (bastante rápida).

Para obtener un fichero binario usamos el operador de redirección de Linux.

También se puede acceder a IPFS por dos métodos más:

FUSE

Podemos montar un sistema de ficheros en Linux gracias a FUSE que es una puerta a IPFS.

Y tendrás acceso a carpetas /ipfs/hash/ integradas en tu sistema. Muy útil si lo queremos integrar en aplicaciones.

GATEWAY HTTP

Podemos usar IPFS sin tener instalado nada, usando la puerta de acceso que alguien generosamente proporcione a la red. La puerta se encargará de llevar el contenido IPFS al mundo cliente-servidor de HTTP. Existen varias, de hecho cada nodo tiene un servidor HTTP en localhost para esto mismamente, pero aquí voy a mencionar dos: la de IPFS.io y la de CloudFare.

Esto sirve para llevar IPFS a cualquier ordenador a través de un navegador web tradicional como Chrome, Firefox o Safari. También facilita la tarea de integrar IPFS en aplicaciones que no tengan desarrollada una librería específica.

Añadir archivos

Ahora vamos a poner en la red IPFS nuevos archivos. Para ello usamos ipfs add.

Esta operación genera el hash que identifica al contenido en la red y que tendremos que enviar a las personas que queramos que accedan al contenido.

La red IPFS de este modo es semi-privada, ya que sin saber el hash no podemos acceder al contenido en cuestión.

Y ya estaría, así de simple. También podemos añadir carpetas.

El último hash que se ve en la pantalla hace referencia a la carpeta entera.

Pining

Por defecto, IPFS almacena los archivos propios del nodo (los que hemos añadido con ipfs add). Pero entonces IPFS no supone ninguna ventaja respecto a HTTP. No es distribuido, solo hay una copia de los ficheros en el universo.

Cuando descargamos un fichero, IPFS guarda en caché una copia para ofrecer a la red, haciendo que sea un sistema distribuido de verdad. No obstante si estamos realmente interesados en conservar el fichero en nuestro nodo a disposición de la red IPFS tenemos que hacer pin (ipfs add). Cuando nos deje de interesar conservar el fichero a la red, podemos quitar el pin (ipfs rm).

Más cosas

Todavía nos quedan muchas cosas de IPFS que ver, como el versionado, el sistema de nombres IPNS, el sistema de enlazado semántico IPLD y como podemos usar IPFS para páginas y aplicaciones web.

 

Yew, crea webapps al estilo Angular/React en Rust

Hoy os traigo una librería muy potente y muy útil, ahora que Rust compila a WebAssembly de forma nativa. Se trata de Yew, una librería para diseñar frontends, single-page-applications y en general, una librería que es una alternativa a Angular, React, Vue y Elm.

En particular, Yew se basa en The Elm Architecture, por lo que los usuarios de Elm serán los que encuentren más familiar a Yew.

Yew significa tejo. He aquí uno de los tejos más famosos de Valladolid, en la plaza del Viejo Coso

Instalar cargo-web y el soporte a WebAssembly

Antes de empezar a programar necesitaremos instalar un plugin para Cargo, llamado cargo-web, que nos ayudará en el desarrollo web con Rust. Por otro lado, hace falta instalar el soporte de Rust a WebAssembly. Existen tres opciones actualmente: asmjs-unknown-emscripten, wasm32-unknown-emscripten y wasm32-unknown-unknown. Para los primeras opciones hace falta tener instalado Emscripten. Para la última, no hace falta nada, por lo que es mi opción recomendada. Por otro lado, wasm32 significa WebAssembly y asmjs es asm.js, que es simplemente JavaScript y será compatible con más navegadores.

The Elm Architecture

Los principios de The Elm Architecture se basan en: modelo, mensajes, actualización y vista.

Para este tutorial vamos a hacer la típica aplicación de una lista donde guardamos notas. Nuestro modelo se va a componer de una lista de tareas, para simplificar, pongamos que una tarea es simplemente un String y un ID. Entonces también nos hará falta almacenar un contador para ir poniendo IDs. También, al tener un campo de texto, nos hará falta una variable para ir almacenando temporalmente lo que escribe el usuario.

Lo siguiente es diseñar los mensajes. Los mensajes interactúan con el modelo y desencadenan una actualización de la vista. En esta aplicación solo nos hacen falta dos mensajes: añadir mensaje y borrar mensaje. Pero como tenemos un campo de texto, tenemos que introducir un mensaje Change y siempre viene bien un mensaje que no haga nada.

Una vez hecho esto pasamos a crear la función update, en la que hacemos distintas cosas según el mensaje que recibamos.

Así pues, si se lanza un mensaje Msg::Add lo que hacemos es copiar el valor de la variable temporal input, crear una nueva tarea con su ID y añadirla a la lista de tareas. Ya está. Yew mágicamente actualizará la página para reflejar que la lista de tareas ha sido modificada. Lo mismo pasa con Remove.

Ahora vamos a las vistas. Una vista es una función que devuelve Html<Msg> y se pueden componer varias funciones así. En nuestro caso, tenemos una vista principal donde se ve un campo de texto y un sitio donde se ejecuta un bucle for con las tareas del modelo. Y a cada tarea se le aplica la vista view_task.

La macro html! nos permite escribir HTML directamente en Rust, con algunas diferencias (¡prestad atención a las comas!). También nos permite introducir código Rust (entre llaves) y closures (observad onclick, oninput y onkeypress).

Finalmente en el método main, inicializamos el modelo y llamamos a program, que empieza a ejecutar Yew.

El código final queda así.

Ejecutando la aplicación web

Usando cargo web, es muy sencillo generar la aplicación web. Simplemente ejecuta:

El resultado, se montará en un mini servidor web. Si accedes a la URL que indica Cargo con tu navegador web, verás algo similar a esto:

Añade items y bórralos. Observa como la aplicación funciona perfectamente.

Distribuyendo la aplicación

Realmente cargo web ha hecho muchas cosas por nosotros. Si nosotros queremos usar Yew en la vida real, no usaremos cargo web. Para ello, compilamos la aplicación web:

Y accedemos a la carpeta target/wasm32-unknown-unknown/release. Allí encontraremos dos archivos que vamos a necesitar. Uno acabado en .js y otro acabado en .wasm. Ambos ficheros deberemos copiarlos donde queramos usarlos. Por último, será necesario un fichero HTML. En el fichero HTML solo hace falta cargar el fichero JS. Yew hará el resto.

Si quieres saber más, puedes descargarte el código de ejemplo que se encuentra en GitHub.

Estadísticas del blog, versión 2017

Antes de acabar el año, es momento de hacer un repaso a las estadísticas del blog. Sé que el año no ha acabado, pero no creo que vaya a haber muchos cambios hasta que sean las campanadas.

Usuarios

En general 2017 ha sido un muy buen año. A fecha del 10 de diciembre he recibido 24.677 sesiones, de 19.618 usuarios y 29.925 visitas a páginas (al acabar diciembre serán más de 30.000 fácilmente). Todo esto sin contar a la gente que entra con un bloqueador de anuncios, que puede bloquear Google Analytics también. Según PageFair, en España el 19% de los usuarios de escritorio usan un AdBlocker. La gráfica que se dibuja es un poco rara sin embargo.

Prácticamente se ve plana debido al gran pico que hubo a finales de julio. De esta gráfica solo se puede apreciar otro pico el 20 de abril. Estos picos se relacionan con dos de los artículso más leídos este año en el blog.

El público no ha evolucionado mucho. Ha aumentado ligeramente el procentaje de mujeres y han aumentado los grupos de edad más alta, mientras que la franja 18-24 ha sufrido un descenso.

En el idioma tampoco hay grandes sorpresas. La mayoría entráis con español, catalán o en-us (que no deja de ser una configuración por defecto muy común). Las visitas en alemán, francés las achaco principalmente a emigrantes y portugués de Brasil a que mucha gente de allí sabe algo de español.

Si bien otros años estaba más compensada la cosa, este año España acapara la mayor parte de las visitas (15.227). Le sigue muy de lejos, pero de forma nada despreciable Méxio y Argentina (1.588 y 1.003 respectivamente). Para completar los 10 países que más visitan mi blogn tenemos a Colombia, Estados Unidos, Chile, Venezuela, Perú, Alemania y Reino Unido.

Estados Unidos ya lleva siendo durante bastantes años un país hispano más, relativamente potente, en lo que es este blog y como siempre, me sorprende la falta de presencia de algunos países latinoamericanos como Uruguay o Ecuador, que podrían estar perfectamente por encima de Alemania o Reino Unido.

Tecnología

Respecto a los navegadores hay una tendencia clara en el uso de Chrome. Firefox se mantiene en segunda posición y Safari consolida su tercera posición. Vemos que Edge todavía no ha superado a Internet Explorer en este blog. El navegador más extraño con el que se ha accedido a mi blog es Puffin.

En sistemas operativos no hay apenas cambios. Windows y Android siguen siendo los reyes. Mención especial a aquellos que usan Firefox OS y BlackBerry.

Adquisición

Esta es una de mis partes preferidas, saber de dónde venís. Menéame repite como una web desde las que entra más tráfico al blog (este año este blog llegó a portada). Google aporta muchas visitas, como el gran buscador. RSS en realidad es una categoría peligrosa, puesto que hay varios sitios que toman la fuente RSS (planetas, bots, …). Finalmente, Facebook parece despegar, aunque Twitter sigue arriba. Mención especial a Instagram (sorprendente para mí, la verdad) y… sigo sin saber como se contabilizan tantas visitas desde ads.adpv.com, pero creo que es un error en algún sitio.

Otras webs que me han enlazado: foroantiusura.org, hispachan.org, Pocket, iessanvicente.com, campusvirtual.uva.es, aulas.inf.uva.es, Mastodon, rust.libhunt.com, GNU Social, www3.gobiernodecanarias.org, … Desde el infame DesdeLinux todavía llega gente a mi blog…

Contenido

Y si, llegó la hora de saber cuáles han sido las páginas más vistas. La ganadora indiscutible es Todo lo que debes de saber sobre las tarjetas de crédito, débito y prepago, un artículo algo diferente en el blog, sobre uno de los muchos temas secundarios que me interesan y que gustó mucho. Este artículo causó el pico de finales julio. A continuación un clásico, Tutorial de GnuCash, que fue publicada el año anterior y sigue atrayendo a miles de personas. ¿Os acordáis del pico de abril? Fue provocado por Novedades de C++17. Y es que, a la gente le interesa mucho C++. Y solo después de estos tres artículos tenemos a la portada del blog. El tutorial de Rust, de CMake y de WiX también han recibido bastantes visitas. Y el artículo de la Calculadora de 4 bits sigue recibiendo muchas visitas desde el año 2013 (es de los que estaban en el primer Blogger del principio).

¿Qué pasa con Elixir?

Desde hace un tiempo oigo a bastante gente hablar de Elixir. Elixir es un lenguaje de programación de propósito general que vio la luz en 2011. Con bastantes aspectos de un lenguaje de programación funcional y dinámico, está especificamente diseñado para manejar la concurrencia. Se ejecuta sobre la máquina virtual BEAM, originalmente diseñada para Erlang y es capaz de ejecutar código métodos escritos en Erlang sin ninguna complicación extra. Además dispone de un sistema de compilación llamado mix, un gestor de paquetes llamado hex y la forma de escribir documentación es similar a Python (existe help(método), ¡aleluya!). Elixir además dispone de hot swapping, es decir, permite cambiar el código en ejecución sin necesidad de parar el programa. También le caracteriza tener un buen soporte a operaciones asíncronas.

¿Es Elixir el nuevo Ruby?

Mucha gente ha querido llamar a Elixir el Erlang escrito bonito. Muchos lo comparan con Ruby pues sí que comparten alguna característica común en su sintaxis y una filosofía en general de simplicidad. Además Elixir es mucho más rápido y está mucho mejor diseñado para concurrencia y aplicaciones tolerantes a fallos (como su hermano mayor Erlang).

Sin embargo, ¿es justo comparar Ruby con Elixir?

Entra Phoenix en acción

Mucha de la popularidad de Ruby se la debe a su framework Rails. Usado por una gran cantidad de sitios en la web, supuso para muchos su primer contacto con Ruby y la razón de que se quedasen aprendiendo el lenguaje.

Curiosamente, Elixir también tiene un framework web que atrae a desarrolladores. Se trata de Phoenix.

Phoenix se presenta como un framework para la nueva web. Aplicaciones realtime, tolerantes a fallos y de alto rendimiento sin perder las facilidades y comodidades de frameworks anteriores. La gente que lo ha usado cuenta maravillas. ¿Has usado Phoenix? Cuéntanos tu experiencia en los comentarios.

Probando Elixir con su REPL

Elixir viene con un REPL, es decir, una terminal donde línea a línea podemos ir introduciendo código Elixir. Se ejecuta con el comando iex.

Podemos hacer un hola mundo con IO.puts.

Podemos probar a definir un módulo de suma:

Lo que se ve en amarillo es el bytecode compilado para BEAM del módulo Adder

Aunque llegado el momento quizá nos interese crear alguna función anónima.

Es fácil encontrar documentación en español sobre Elixir si deseas investigar más sobre el tema.

Sin duda Elixir parece interesante. ¿Será un mero hype o dentro de unos años Elixir será uno de los lenguajes más populares? Ciertas webs han empezado a recomendar echar un vistazo a Elixir y Phoenix si queremos crear una nueva aplicación web.

Tutorial de Rocket, echa a volar tus webapps con Rust

Previamente ya hemos hablado de Iron como un web framework para Rust. Sin embargo desde que escribí ese post ha surgido otra librería que ha ganado mucha popularidad en poco tiempo. Se trata de Rocket. Un web framework que propone usar el rendimiento que ofrece Rust sin sacrificar la facilidad de uso de otros lenguajes.

Rocket lleva las pilas cargadas

A diferencia de Iron, Rocket incluye bastantes prestaciones por defecto con soporte para:

  • Plantillas
  • Cookies
  • Formularios
  • JSON
  • Soporte para rutas dinámicas

Un “Hola Mundo”

Rocket necesita una versión nightly del compilador de Rust. Una vez lo tengas creamos una aplicación con Cargo.

Ahora modificamos el fichero Cargo.toml generado en la carpeta rocket_app para añadir las siguientes dependencias:

Editamos el archivo src/main.rs para que se parezca algo a esto:

Con esto iniciamos Rocket y dejamos a la función index que gestione las peticiones GET encaminadas a /. El servidor devolverá El cohete ha despegado.

Ahora si ejecutamos cargo run veremos algo similar a esto:

Vemos que el servidor ya está escuchando en el puerto 8000 y está usando todos los cores (en mi caso 4) del ordenador.

Configurar Rocket

Rocket dispone de varias configuraciones predeterminadas que afectan a su funcionamiento. Para alternar entre las configuraciones debemos usar variables de entorno y para modificar las configuraciones en sí debemos usar un fichero llamado Rocket.toml.

Las configuraciones por defecto son: dev (development), stage (staging) y prod (production). Si no indicamos nada, Rocket se inicia con la configuración dev. Para arrancar con la configuración de producción modificamos el valor de ROCKET_ENV.

Sería el comando para arrancar Rocket en modo producción. En el archivo Rocket.toml se puede modificar cada configuración, estableciendo el puerto, el número de workers y parámetros extra pero no vamos a entrar en ello.

Rutas dinámicas

Rocket soporta rutas dinámicas. Por ejemplo, si hacemos GET  /pelicula/Intocable podemos definir que la parte del nombre de la película sea un parámetro. Esto hará que la función encargada de /pelicula/Intocable y de /pelicula/Ratatouille sea la misma.

Los argumentos de la función son los parámetros de la petición GET. ¿Qué pasa si no concuerda el tipo de la función con lo que se pasa por HTTP? Nada. Sencillamente Rocket ignora esa petición, busca otra ruta (puede haber sobrecarga de rutas) y si encuentra otra que si satisfaga los parámetros será esa la escogida. Para especificar el orden en el que se hace la sobrecarga de rutas puede usarse rank. En caso de no encontrarse nada, se devuelve un error 404.

POST, subir JSON y formularios

Rocket se integra con Serde para lograr una serialización/deserialización con JSON inocua. Si añadimos las dependencias serde, serde_json y serde_derive al fichero Cargo.toml podemos tener un método que acepete una petición POST solo para mensajes del tipo application/json con deserialización incorporada.

Si el JSON no se ajusta a la estructura User simplemente se descarta devolviendo un error 400.

Lo mismo que es posible hacer con JSON puede hacerse con formularios usando el trait FromForm.

Errores

En Rocket, como es lógico, es posible crear páginas personalizadas para cada error.

La lista de métodos que manejan errores hay que pasarla en el método catch de rocket::ignite

Respuestas

Rocket nos permite devolver cualquier cosa que implemente el trait Responder. Algunos tipos ya lo llevan como String, File, JSON, Option y Result. Pero nada nos impide que nuestros propios tipos implementen Responder. Con Responder tenemos el contenido y el código de error (que en la mayoría de casos será 200). En el caso de Result es muy interesante, pues si Err contiene algo que implementa Responder, se devolverá la salida que implemente también, pudiendo así hacer mejores respuestas de error, mientras que si no lo hacen se llamará al método que implemente el error 500 de forma genérica. Con Option, si el valor es Some se devolverá el contenido, si es None se generará un error 404.

Este ejemplo para /pelicula/Intocable devolverá: La película Intocable se hizo en Francia mientras que para /pelicula/Ratatouille dirá No existe esa película en nuestra base de datos.

También es posible devolver plantillas. Rocket se integra por defecto con Handlebars y Tera, aunque no es muy costoso añadir cualquier otra como Maud.

Conclusión

Rocket es un prometedor web framework para Rust, bastante idiomático, que se integra muy bien con el lenguaje. Espero con ansia las nuevas veriones. Es posible que la API cambie bastante hasta que salga la versión 1.0, no obstante así es como ahora mismo funciona.