Modo Router de Faucet
El modo router de Faucet te permite servir múltiples aplicaciones distintas desde una única instancia de Faucet. Cada aplicación, o "ruta", puede tener su propia configuración (como tipo de aplicación, directorio de trabajo, número de workers y estrategia de balanceo de carga) y es accesible a través de un prefijo de ruta URL único.
Esto es particularly útil para:
- Alojar múltiples aplicaciones Shiny, APIs de Plumber o documentos Quarto Shiny en el mismo servidor y puerto.
- Desplegar diferentes versiones o configuraciones de la misma aplicación bajo diferentes rutas.
- Consolidar tus despliegues de aplicaciones R en un único proceso de Faucet.
Resumen en Video
Para una demostración visual de la característica del router de Faucet, revisa el siguiente video:
Activación del Modo Router
Para ejecutar Faucet en modo router, utilizas el subcomando router
:
faucet router [OPCIONES]
La opción principal para el modo router es especificar el archivo de configuración:
- CLI:
--conf <RUTA_AL_ARCHIVO_DE_CONFIGURACION>
o-c <RUTA_AL_ARCHIVO_DE_CONFIGURACION>
- Variable de Entorno:
FAUCET_ROUTER_CONF=<RUTA_AL_ARCHIVO_DE_CONFIGURACION>
- Por Defecto: Si no se especifica, Faucet buscará un archivo llamado
frouter.toml
en el directorio de trabajo actual (./frouter.toml
).
Las opciones globales de Faucet como --host
, --ip-from
, --rscript
, --quarto
y las configuraciones de telemetría (por ejemplo, --pg-con-string
) se aplican a toda la instancia del router y a todas las rutas que gestiona.
Archivo de Configuración (frouter.toml
)
El modo router se configura mediante un archivo TOML. Este archivo debe definir un array llamado route
, donde cada elemento del array es un objeto que configura una ruta de aplicación específica.
Aquí está la estructura de un único objeto de ruta dentro del archivo frouter.toml
:
[[route]]
# El prefijo de la ruta URL para esta aplicación.
# Este prefijo DEBE terminar con una barra inclinada (ej., "/app/", "/api/v1/").
# Si es la ruta raíz, debe ser "/".
# (Requerido)
route = "/mi_aplicacion/"
# El tipo de aplicación.
# (Requerido)
# Posibles valores: "plumber", "shiny", "quarto-shiny"
# Alias como "Plumber", "Shiny", "QuartoShiny" también son aceptados.
server_type = "shiny"
# El directorio de trabajo para esta aplicación específica.
# Archivos como app.R o plumber.R se buscarán en relación con este directorio,
# o dentro de `app_dir` si se especifica. Las rutas pueden ser relativas (a donde está frouter.toml) o absolutas.
# (Opcional, por defecto es "." - el directorio donde se encuentra frouter.toml)
workdir = "./apps/mi_app_shiny"
# El subdirectorio dentro de `workdir` donde se encuentra el archivo principal de la aplicación (ej., app.R).
# Si tu app.R está directamente en `workdir`, puedes omitir esto o configurarlo como ".".
# (Opcional)
app_dir = "source" # Busca ./apps/mi_app_shiny/source/app.R
# El número de procesos worker a generar para esta aplicación.
# (Requerido)
workers = 2
# La estrategia de balanceo de carga para esta aplicación.
# (Opcional, los valores por defecto dependen del tipo de aplicación: "ip-hash" para shiny/quarto-shiny, "round-robin" para plumber)
# Posibles valores: "round-robin", "ip-hash", "cookie-hash"
strategy = "ip-hash"
# Ruta al documento Quarto (.qmd), requerido si server_type es "quarto-shiny".
# La ruta debe ser relativa a `workdir` o una ruta absoluta.
# (Opcional, pero requerido para quarto-shiny)
# qmd = "dashboard.qmd"
Campos Explicados:
route
(String, Requerido): El prefijo de la ruta URL. Este prefijo debe terminar con una barra inclinada (ej.,/app/
,/api/v1/
) a menos que sea la ruta raíz (/
). Faucet dirigirá las solicitudes que comiencen con esta ruta a la aplicación configurada.server_type
(String, Requerido): Determina el tipo de aplicación R. Debe ser uno deplumber
,shiny
oquarto-shiny
. Alias comoPlumber
,Shiny
,QuartoShiny
también son aceptados.workdir
(String, Opcional): El directorio de trabajo base para la aplicación. Si no se especifica, por defecto es el directorio donde se está ejecutando Faucet (típicamente donde se encuentrafrouter.toml
). Las rutas paraapp_dir
yqmd
se resuelven típicamente en relación con este.app_dir
(String, Opcional): Un subdirectorio dentro deworkdir
que contiene el archivo principal de la aplicación (por ejemplo,app.R
para Shiny,plumber.R
para Plumber). Por ejemplo, siworkdir = "./mi_coleccion_apps"
yapp_dir = "app_especifica_src"
, Faucet buscará./mi_coleccion_apps/app_especifica_src/app.R
. Si el archivo principal está directamente enworkdir
, puedes omitir esto o usarapp_dir = "."
.workers
(Integer, Requerido): El número de procesos worker de R a lanzar para esta ruta específica. Debe ser un entero positivo.strategy
(String, Opcional): La estrategia de balanceo de carga para esta ruta.- Para aplicaciones
shiny
yquarto-shiny
, generalmente se recomiendaip-hash
y es el valor por defecto para asegurar la persistencia de la sesión. - Para APIs
plumber
,round-robin
es el valor por defecto común. - Opciones disponibles:
round-robin
,ip-hash
,cookie-hash
.
- Para aplicaciones
qmd
(String, Opcional): Siserver_type
esquarto-shiny
, este campo es requerido y debe especificar la ruta al archivo.qmd
. Esta ruta es típicamente relativa aworkdir
.
Importante: Cada valor de route
en el archivo de configuración debe ser único. Rutas duplicadas harán que Faucet termine con un error al iniciarse.
Comportamiento del Enrutamiento y Eliminación de Prefijo de Ruta (Path Stripping)
Cuando Faucet recibe una solicitud HTTP en modo router:
- Itera a través de las definiciones
[[route]]
enfrouter.toml
en el orden en que están definidas. - Coincidencia de Rutas y Orden:
- Para cada ruta definida, Faucet comprueba si la ruta URL de la solicitud entrante comienza con el prefijo
route
de la ruta. - Se utiliza la primera ruta que coincida. Esto significa que el orden de tus rutas en
frouter.toml
es crítico. Las rutas más específicas (ej.,/app/feature1/
) deben listarse antes que las rutas más generales (ej.,/app/
) si comparten una ruta base común, para evitar que la ruta general "sombreé" a la específica. La ruta raíz/
generalmente debe listarse al final.
- Para cada ruta definida, Faucet comprueba si la ruta URL de la solicitud entrante comienza con el prefijo
- Eliminación de Prefijo de Ruta (Path Stripping):
- Todos los prefijos
route
(excepto la ruta raíz/
) deben terminar con una barra inclinada (/
). - Una vez que se encuentra una ruta coincidente, su prefijo
route
definido se elimina del inicio de la ruta URL de la solicitud. - La parte restante de la ruta se reenvía entonces a la aplicación configurada para esa ruta.
- Ejemplo: Si se define
route = "/myapp/"
:- Una solicitud a
/myapp/usuarios/1
hace que la aplicación vea/usuarios/1
. - Una solicitud a
/myapp/
(con la barra inclinada final) hace que la aplicación vea/
.
- Una solicitud a
- Ejemplo: Si se define
route = "/"
:- Una solicitud a
/pagina
hace que la aplicación vea/pagina
. - Una solicitud a
/
hace que la aplicación vea/
.
- Una solicitud a
- Todos los prefijos
- Si se encuentra una ruta coincidente, la solicitud (con la ruta potencialmente modificada) se entrega a la instancia del servidor Faucet que gestiona esa aplicación específica, la cual luego aplica su estrategia de balanceo de carga configurada para seleccionar un worker.
- Si ninguna
route
configurada coincide con la ruta de la solicitud entrante, Faucet devuelve una respuesta404 Not Found
.
Ejemplo de frouter.toml
Este ejemplo se basa en faucet-router-example
disponible en el repositorio de GitHub de Faucet bajo el directorio examples/
. Para ejecutar este ejemplo, navega a examples/faucet-router-example-main/
y ejecuta faucet router
.
# frouter.toml
# Este archivo está ubicado en examples/faucet-router-example-main/
# Ruta para la aplicación Shiny "sliders".
# `workdir` está configurado como "./sliders", entonces Faucet busca app.R
# en examples/faucet-router-example-main/sliders/app.R
[[route]]
route = "/sliders/"
workers = 1
server_type = "shiny" # Nota: "Shiny" (con mayúscula) también es aceptado
workdir = "./sliders"
# Ruta para la aplicación Shiny "text".
# `workdir` por defecto es "." (donde está frouter.toml).
# `app_dir` es "./text", entonces Faucet busca app.R
# en examples/faucet-router-example-main/text/app.R
[[route]]
route = "/text/"
workers = 1
server_type = "shiny"
app_dir = "./text"
# Ruta para un documento Quarto Shiny.
# `workdir` es "./qmd".
# `qmd` especifica "old_faithful.qmd" relativo a workdir.
# Faucet busca examples/faucet-router-example-main/qmd/old_faithful.qmd
[[route]]
route = "/qmd/"
workers = 1
server_type = "quarto-shiny" # Nota: "QuartoShiny" (con mayúscula) también es aceptado
workdir = "./qmd"
qmd = "old_faithful.qmd"
# Ruta para una API de Plumber.
# `workdir` es "./api". Faucet busca plumber.R
# en examples/faucet-router-example-main/api/plumber.R
[[route]]
route = "/api/"
workers = 1
server_type = "plumber" # Nota: "Plumber" (con mayúscula) también es aceptado
workdir = "./api"
strategy = "round-robin"
# Ruta raíz para la aplicación Shiny principal.
# `workdir` por defecto es "." (donde está frouter.toml).
# Faucet busca app.R en examples/faucet-router-example-main/app.R
# Esta ruta se coloca al final para evitar solapar otras rutas específicas.
[[route]]
route = "/"
workers = 1
server_type = "shiny"
strategy = "cookie-hash"
Con la configuración anterior, si Faucet se está ejecutando en http://localhost:3838
desde el directorio examples/faucet-router-example-main/
:
- Las solicitudes a
http://localhost:3838/sliders/
serían enrutadas a la aplicación Shiny en el subdirectoriosliders
. - Las solicitudes a
http://localhost:3838/text/
serían enrutadas a la aplicación Shiny en el subdirectoriotext
. - Las solicitudes a
http://localhost:3838/qmd/
serían enrutadas al documento Quarto Shinyold_faithful.qmd
. - Las solicitudes a
http://localhost:3838/api/echo?msg=hola
serían enrutadas a la API de Plumber en el subdirectorioapi
(la API vería/echo?msg=hola
). - Las solicitudes a
http://localhost:3838/
serían enrutadas alapp.R
en la raíz del directoriofaucet-router-example-main
.
Nota sobre el Orden de las Rutas: Recuerda que si tienes rutas con rutas base superpuestas (ej., /datos/especifico/
y /datos/
), debes listar la ruta más específica (/datos/especifico/
) antes que la ruta más general (/datos/
) en tu archivo frouter.toml
. De lo contrario, la ruta general /datos/
coincidiría con las solicitudes destinadas a /datos/especifico/
, y nunca se alcanzaría la ruta específica. La ruta raíz /
típicamente debería ser la última entrada.
Este modo router proporciona una forma flexible de gestionar y servir múltiples aplicaciones R eficientemente usando una única instancia de Faucet.