ExyonQ Servidor HTTP modular y reverse proxy en Rust

Serverfile

Un Serverfile (.exy) es una superficie mínima para describir un listener con rutas y compilarlo a IR. No es el lenguaje principal del producto: el IR TOML es la fuente de verdad y el .exy es una comodidad de arranque.

Aviso de alcance: el repositorio no documenta la sintaxis .exy en detalle. exyonq explain remite a docs/architecture/p1.4-exy-to-ir-mapping.md, un documento que no está presente en este árbol. Esta página se limita a lo verificable: el analizador de config/surface, la salida real de compile y fmt, y las limitaciones que se deducen de ambos.

Sintaxis verificable

Un fichero empieza por la cabecera de listener, con un bloque entre llaves:

:8080 {
    route /api {
        proxy backend 9000
    }
}

Dentro del bloque del listener:

DirectivaFormaEfecto en el IR
route <ruta> { … }ruta absolutaUn [[route]] con match = { path = … }
metrics onon u otro valor[modules.metrics] enabled = true
compression onon o gzip[modules.compression] enabled = true
ratelimit <rps> [burst N]entero con sufijo libre[modules.ratelimit] con requests_per_second y burst

Dentro de un bloque de ruta:

DirectivaFormaEfecto
proxy <nombre> <puerto>puerto numéricoupstream = "<nombre>" y un [[upstream]] con target = "http://127.0.0.1:<puerto>"
proxy … timeout 5sNms o Nstimeout_ms del upstream (30000 por defecto)
root <directorio>rutaroot de la ruta
index <fichero>nombreindex de la ruta

Los comentarios empiezan por #. El listener :8080 se normaliza a 0.0.0.0:8080; una cabecera con host y puerto se conserva tal cual.

Compilar a IR

exyonq compile site.exy

Entrada:

:8080 {
    route /api {
        proxy backend 9000
    }
}

Salida real:

config_version = 1
# generated by exyonq compile

[[server]]
listen = "0.0.0.0:8080"
routes = ["api"]

[[route]]
name = "api"
match = { path = "/api" }
upstream = "backend"

[[upstream]]
name = "backend"
target = "http://127.0.0.1:9000"

Tres detalles que conviene saber:

Con -o escribe el fichero y responde wrote site.toml; con --check valida sin escribir; con --profile dev|edge|lb aplica un perfil de producto y reemite el TOML.

Formatear

exyonq fmt site.exy        # imprime
exyonq fmt -w site.exy     # reescribe

fmt normaliza la sangría a cuatro espacios, expande las rutas de una línea a bloque y normaliza el rate limit a la forma <n>r/s:

:8080 {
    route /api {
        proxy backend 9000
    }
    route / {
        root /var/www/html
        index index.html
    }
    metrics on
    compression on
    ratelimit 100r/s burst 200
}

Explicar

exyonq explain route
exyonq explain proxy
exyonq explain pools_fcgi

Cada término devuelve meaning, surface, ir_mapping, required, default, allowed_values, related_codes y documentation. Es la forma más rápida de saber a qué tabla del IR corresponde una directiva.

Migrar de v1 a v2

exyonq compile site.exy -o site.v1.toml
exyonq migrate-config -c site.v1.toml -o site.v2.toml

La migración añade config_version = 2 y materializa los valores por defecto que la v1 dejaba implícitos: un upstream sin timeout_ms aparece con timeout_ms = 30000. El fichero de entrada no se toca.

Qué no cubre

Para producción, escribe IR TOML directamente. El .exy sirve para arrancar en un minuto y para entender el modelo antes de complicarlo.