En nuestra era, la de la revolución y transformación digital, la de las aplicaciones web y las aplicaciones móviles que exigen la transmisión de datos en tiempo real de servidores a clientes, la de los chats reinventados, la de las notificaciones, la de Node.js y Websockets, PHP, en especial Symfony no quiere quedarse detrás de la competencia, y el equipo desarrolló sobre el protocolo Mercure un componente sencillo para estos casos de uso.

¿Qué es Mercure?

Según su presentación Mercure “es un protocolo abierto que permite enviar actualizaciones de datos a navegadores web y otros clientes HTTPs de una manera conveniente, rápida, confiable y de una forma amigable con la batería. Mercure es útil para publicar actualizaciones en tiempo real de recursos servidos a través de APIs web, a aplicaciones web y móviles reactivas.

Protocolo moderno

Mercure es por tanto, un protocolo que quiere ganar ventaja sobre Websockets y ser una alternativa si hace falta, y es útil para añadir capacidades de streaming a APIs REST y GraphQL. Además, Mercure está desarrollado sobre Server-sent events, y es soportado de forma nativa por los navegadores modernos, aplicaciones móviles y dispositivos IoT. Mercure viene con un mecanismo de autorización, reconexión automática y es compatible con HTTP/2, y HTTP/3.

Si quieres saber más información sobre Mercure, puedes acceder a su página web oficial, o incluso a su documentación.

Casos de uso de Mercure

Creo que ya estás visualizando los casos de uso de Mercure.  Los siguientes son algunos de ellos:

  • Disponibilidad online: si tu app necesita mostrar al instante que el producto ya no está disponible
  • Trabajos de computación asíncronos: Cuando tu aplicación necesita enviar un informe si algún proceso ha finalizado.
  • Edición colaborativa: Si tu aplicación permite que diferentes usuarios editen un documento al mismo tiempo, los cambios se emiten inmediatamente a los demás usuarios.

¿Cómo es el componente Mercure de Symfony?

El componente Mercure de Symfony implementa la parte publisher de Mercure, que no es nada más que un servidor de aplicaciones, o un navegador web.

Iniciar Mercure con Docker

Antes de probar con el componente de Symfony, puedes instalar Mercure de varias formas. Gracias a una imagen de Docker disponible en Docker Hub, ejecutando el siguiente comando en tu consola tendràs funcionando un servidor en modo demostración:

docker run \ -e JWT_KEY='!ChangeMe!' -e DEMO=1 -e ALLOW_ANONYMOUS=1 -e PUBLISH_ALLOWED_ORIGINS='http://localhost' \ -p 80:80 \ dunglas/mercure

Si todo ha ido bien, tu nuevo servidor (tu Mercure Hub)  estará disponible en http://localhost.

Nuevo servidor de Mercure ejecutándose localmente. 

El Hub de Mercure permite gestionar conexiones persistentes, ya que, como hemos dicho antes, es un servidor dedicado que maneja conexiones SSE (Eventos enviados por servidor) persistentes con los clientes. La funcionalidad se entiende de relativamente fácil: tu aplicación de Symfony publica las actualizaciones al hub, y el hub las emite a los clientes. ¿Interesante?

_images/schema.png
Cómo funciona el Hub de Mercure by symfony.com

¿Cómo usarlo en Symfony 5?

En tu APP de Symfony 5, lo único que tienes que hacer es instalar el componente como siempre:

composer require symfony/mercure

Una vez instalado el componente, puedes configurar el bundle MercureBundle mediante variables de entorno (.env). Recuerda que envés de definir tus variables de entorno en tu servidor web, u otro sitio cualquiera, Symfony te permite hacerlo dentro de un fichero .env localizado en la raíz de tu proyecto. ¿Cómo funciona? El fichero .env se lee y se analiza en cada petición y sus valores se añaden a las variables de PHP $_ENV y $_SERVER.

Entonces, en tu fichero .env añades la URL de tu hub como valor de la variable MERCURE_PUBLISH_URL. (p.e.: MERCURE_PUBLISH_URL=http://localhost/.well-known/mercure).

Además, tu aplicación Symfony debe llevar un JWT (JSON Web Token) al Hub de Mercure para ser autorizada a publicar actualizaciones. Debes añadir tu JWT en la variable MERCURE_JWT_TOKEN.

“Puedes crear y firmar JWTs en jwt.io

Servicio Publisher en un controlador de Symfony

El componente de Mercure proporciona un valor de objeto Update que representa una actualización a publicar y también un servicio Publisher para enviar actualizaciones al Hub. Usando “autowiring”, puedes inyectar el Publisher en cualquier otro servicio. Por tanto en un controlador podrías tener lo siguiente:

Controlador Publisher

El primer parámetro del constructor Update es el tópico que se está actualizando, en este caso es una URL, pero podría ser cualquier IRI válido. El segundo parámetro es el contenido a actualizar. Symfony recomienda serializarlo en formatos del tipo JSON-LD, Atom, HTML, o XML.

¿Cómo suscribir con JavaScript?

Una vez hayas llegado hasta aquí, ya puedes suscribir a las actualizaciones desde servidor. En JavaScript, y gracias a EventSource puedes suscribir de forma fácil a las actualizaciones.

Ejemplo de cómo suscribirse a actualizaciones en JavaScript

Conclusión

Esta ha sido solamente una breve aproximación a Mercure y al componente Mercure de Symfony. Como has podido ver, el hub es simple de configurar y de gestionar. Además lo puedes integrar con tu Symfony sin tener que montar grandes infraestructuras para este tipo de aplicaciones. En próximas sesiones veremos cómo  poder desarrollar un chat básico utilizando Mercure y Symfony.

¿Qué te parece Mercure? Crees que puede tener alguna ventaja en relación a la competencia?

Te dejo un vídeo en el que puedes ver como una API web de Symfony utiliza Mercure y la API Platform para actualizar en tiempo real un aplicación de React y una aplicación móvil en React Native.

Video ejemplo: Mercure + React + React Native

Foto:  Reimund Bertrams from Pixabay

Fuentes: