Microservicios en Elixir con Plug

Plug es una biblioteca que usada junto a un servidor web como Cowboy o Bandit permite crear cómodamente aplicaciones web mediante un pequeño lenguaje declarativo, sin necesidad de instalar todo un framework como Phoenix, algo que puede ser útil en el mundo de los microservicios. Veamos cómo agregar Plug a un proyecto de Elixir y crear una respuesta HTTP.

Cuando queremos crear una pequeña aplicación web en Elixir, especialmente un microservicio, a veces Phoenix puede resultar demasiado pesado y complejo para lo que necesitamos. Por suerte, Plug nos ofrece una alternativa mucho más ligera y sencilla para construir aplicaciones web con menos código y sin tantas dependencias.

Plug es una biblioteca que nos proporciona una API cómoda y componible para manejar peticiones HTTP. Nos permite escribir el código que se ejecuta cuando alguien hace una petición a nuestra aplicación web, pero no incluye un servidor web por sí misma. Para eso, necesitamos un servidor externo, y en el ecosistema Elixir los más comunes son Cowboy y Bandit. Cowboy es el veterano y más extendido, aunque no está escrito en Elixir, mientras que Bandit es más reciente y está completamente desarrollado en Elixir, con la intención de ser una alternativa moderna. En este caso, optamos por Cowboy por su estabilidad y popularidad.

Para conectar Plug con Cowboy utilizamos la biblioteca plugcowboy, que actúa como una capa de integración entre ambos. Plug nos da las herramientas para escribir aplicaciones web, Cowboy es el servidor que las sirve, y plugcowboy es el pegamento que une estos dos mundos. Si en el futuro decidimos cambiar Cowboy por Bandit, solo tendríamos que modificar esta capa de integración sin tocar el resto de nuestro código basado en Plug. Esto es posible porque Phoenix, por ejemplo, está construido sobre Plug, lo que garantiza cierta estabilidad y compatibilidad a largo plazo.

Para empezar a construir nuestro microservicio, creamos un nuevo proyecto con mix new usando la opción --sup para que incluya un supervisor. Esto nos permite manejar el ciclo de vida de nuestra aplicación de forma robusta. Luego, en el archivo mix.exs, añadimos las dependencias plug y plug_cowboy. Aunque plug_cowboy ya incluye Cowboy, preferimos declarar explícitamente ambas para tener claridad sobre lo que usamos.

Después de descargar las dependencias con mix deps.get y compilar con mix run, podemos comenzar a escribir nuestro handler. Creamos un módulo nuevo, por ejemplo Microservicio.Ruta, donde definimos el comportamiento de nuestro endpoint. Importamos Plug.Conn para tener acceso a las funciones que nos facilitan manipular la conexión HTTP.

En este módulo definimos dos funciones esenciales: init/1 y call/2. La función init recibe opciones iniciales y nos permite preparar el estado de nuestro handler. En este caso, simplemente imprimimos un mensaje para confirmar que se ejecuta y devolvemos las opciones tal cual. La función call es la que se ejecuta con cada petición HTTP. Recibe la estructura conn, que representa toda la información de la conexión, incluyendo método, ruta, parámetros, cabeceras y más, y las opciones inicializadas.

Dentro de call, podemos hacer lo que necesitemos: consultar bases de datos, llamar a otros servicios, o simplemente responder. Para enviar una respuesta usamos send_resp/3 de Plug.Conn, pasando la conexión, el código HTTP (por ejemplo, 200) y el cuerpo de la respuesta. En nuestro ejemplo, devolvemos un simple hola mundo\n. También imprimimos la estructura conn para ver toda la información que contiene.

Para que nuestro handler funcione, lo añadimos al árbol de supervisión en application.ex. Usamos Plug.Cowboy.child_spec/1 para indicarle al supervisor que gestione nuestro plug en el puerto 4000 con el esquema HTTP. Así, cuando iniciemos la aplicación con mix run --no-halt, el servidor queda activo y listo para recibir peticiones.

Al visitar http://localhost:4000 en el navegador, recibimos la respuesta hola mundo y en la consola vemos impresa la estructura completa de la conexión, que incluye parámetros de consulta, cookies, cabeceras y más. Esto nos muestra cómo Plug nos da acceso total a la petición y nos permite manipular la respuesta de forma flexible.

Con esta base, podemos empezar a construir microservicios sencillos en Elixir sin la complejidad de Phoenix, aprovechando la ligereza y modularidad de Plug y Cowboy. En siguientes pasos podríamos, por ejemplo, gestionar parámetros de consulta para personalizar respuestas, manejar rutas diferentes o integrar bases de datos, todo con un código compacto y claro.

Lista de reproducción
  1. 1
    mix
    10 minutos
  2. 2
    Documentando código: comentarios, docs y moduledocs
    10 minutos
  3. 3
    Atributos de módulo
    9 minutos
  4. 4
    Dependencias
    12 minutos
  5. 5
    Un ejemplo práctico de módulo útil
    13 minutos
  6. 6
    Alias e import
    10 minutos
  7. 7
    Sobre las macros, require y use
    11 minutos
  8. 8
    Typespecs (parte 1, usando tipos básicos)
    10 minutos
  9. 9
    Typespecs (parte 2, tipos propios y t())
    11 minutos
  10. 10
    Comportamientos
    11 minutos
  11. 11
    Tratamiento de errores con rescue
    8 minutos
  12. 12
    Elevando errores con raise
    8 minutos
  13. 13
    with
    14 minutos
  14. 14
    Sigilos
    8 minutos
  15. 15
    Tests con ExUnit
    12 minutos
  16. 16
    Más particularidades de ExUnit
    13 minutos
  17. 17
    Microservicios en Elixir con Plug
    11 minutos
  18. 18
    Cómo Plug.Router te ayuda a escribir microservicios en Elixir
    14 minutos
  19. 19
    ¿Cómo hacer rutas dinámicas en Phoenix y Plug?
    13 minutos