Routing
Los routers agrupan endpoints bajo prefijos de URL y aplican middleware compartido. Los endpoints definen manejadores HTTP.
Arquitectura
flowchart TB
S[http.service
:8080] --> R1[http.router
/api]
S --> R2[http.router
/admin]
S --> ST[http.static
/]
R1 --> E1[GET /users]
R1 --> E2[POST /users]
R1 --> E3["GET /users/{id}"]
R2 --> E4[GET /stats]
R2 --> E5[POST /config]
Las entradas referencian padres vía metadatos:
- Routers:
meta.server: app:gateway - Endpoints:
meta.router: app:api
Configuración del Router
- name: api
kind: http.router
meta:
server: gateway
prefix: /api/v1
middleware:
- cors
- compress
options:
cors.allow.origins: "*"
post_middleware:
- endpoint_firewall
| Campo | Tipo | Descripción |
|---|---|---|
meta.server |
ID de Registro | Servidor HTTP padre |
prefix |
string | Prefijo de URL para todas las rutas |
middleware |
[]string | Middleware pre-match |
options |
map | Opciones de middleware |
post_middleware |
[]string | Middleware post-match |
post_options |
map | Opciones de middleware post-match |
Configuración de Endpoint
- name: get_user
kind: http.endpoint
meta:
router: api
method: GET
path: /users/{id}
func: app.users:get_user
| Campo | Tipo | Descripción |
|---|---|---|
meta.router |
ID de Registro | Router padre |
method |
string | Método HTTP (GET, POST, PUT, DELETE, PATCH, HEAD) |
path |
string | Patrón de ruta URL (comienza con /) |
func |
ID de Registro | Función handler |
Parámetros de Ruta
Use sintaxis {param} para parámetros de URL:
- name: get_post
kind: http.endpoint
meta:
router: api
method: GET
path: /users/{user_id}/posts/{post_id}
func: get_user_post
Acceso en handler:
local http = require("http")
local function handler()
local req = http.request()
local user_id = req:param("user_id")
local post_id = req:param("post_id")
-- ...
end
Rutas Comodín
Capture segmentos de ruta restantes con {param...}:
- name: serve_files
kind: http.endpoint
meta:
router: api
method: GET
path: /files/{filepath...}
func: serve_file
-- Solicitud: GET /api/v1/files/docs/guides/readme.md
local file_path = req:param("filepath") -- "docs/guides/readme.md"
El comodín debe ser el último segmento en la ruta.
Funciones Handler
Los handlers de endpoint usan el módulo http para acceder a objetos de solicitud y respuesta. Ver Módulo HTTP para la API completa.
local http = require("http")
local json = require("json")
local function handler()
local req = http.request()
local res = http.response()
local user_id = req:param("id")
local user = get_user(user_id)
res:status(200)
res:write(json.encode(user))
end
return { handler = handler }
Opciones de Middleware
Las opciones de middleware usan notación de punto con el nombre del middleware como prefijo:
middleware:
- cors
- ratelimit
- token_auth
options:
cors.allow.origins: "https://app.example.com"
cors.allow.methods: "GET,POST,PUT,DELETE"
ratelimit.requests: "100"
ratelimit.window: "1m"
token_auth.store: "app:tokens"
token_auth.header.name: "Authorization"
El middleware post-match usa post_options:
post_middleware:
- endpoint_firewall
post_options:
endpoint_firewall.default_policy: "deny"
Middleware Pre-Match vs Post-Match
Pre-match (middleware) se ejecuta antes del matching de ruta:
- CORS (maneja preflight OPTIONS)
- Compresión
- Rate limiting
- Detección de IP real
- Autenticación de token (enriquecimiento de contexto)
Post-match (post_middleware) se ejecuta después de que la ruta es matcheada:
- Firewall de endpoint (necesita info de ruta para autorización)
- Firewall de recurso
- WebSocket relay
middleware: # Pre-match: todas las solicitudes a este router
- cors
- compress
- token_auth # Enriquece contexto con actor/scope
post_middleware: # Post-match: solo rutas matcheadas
- endpoint_firewall # Usa actor de token_auth
endpoint_firewall que usa el actor establecido por token_auth.
Ejemplo Completo
version: "1.0"
namespace: app
entries:
# Servidor
- name: gateway
kind: http.service
addr: ":8080"
lifecycle:
auto_start: true
# Router de API
- name: api
kind: http.router
meta:
server: gateway
prefix: /api/v1
middleware:
- cors
- compress
- ratelimit
options:
cors.allow.origins: "https://app.example.com"
ratelimit.requests: "100"
ratelimit.window: "1m"
# Función handler
- name: get_users
kind: function.lua
source: file://handlers/users.lua
method: list
modules:
- http
- json
- sql
# Endpoints
- name: list_users
kind: http.endpoint
meta:
router: api
method: GET
path: /users
func: get_users
- name: get_user
kind: http.endpoint
meta:
router: api
method: GET
path: /users/{id}
func: app:get_user_by_id
- name: create_user
kind: http.endpoint
meta:
router: api
method: POST
path: /users
func: app:create_user
Rutas Protegidas
Patrón común con autenticación:
entries:
# Rutas públicas (sin auth)
- name: public
kind: http.router
meta:
server: gateway
prefix: /api/public
middleware:
- cors
# Rutas protegidas
- name: protected
kind: http.router
meta:
server: gateway
prefix: /api
middleware:
- cors
- token_auth
options:
token_store: app:tokens
post_middleware:
- endpoint_firewall
Ver También
- Servidor - Configuración del servidor HTTP
- Archivos Estáticos - Servicio de archivos estáticos
- Middleware - Middleware disponible
- Módulo HTTP - API HTTP de Lua