Endpoints y flow de las directivas
Declaración de endpoints
Para declarar endpoints en cualquier API de Hefesto solo tienes que añadirlos al api.yaml, dentro de la sección endpoints. Cada endpoint se define con el verbo HTTP seguido del path:
endpoints:
get /user/{id}:
Ping:
directive: Ping
post /user:
Ping:
directive: Ping
En el ejemplo anterior hemos declarado dos endpoints: un GET a /user/{id} y un POST a /user. Ambos ejecutan una sola directiva llamada Ping, que devuelve un JSON con el mensaje "pong".
Los path params se definen con llaves {id}, y desde las directivas o desde el api.yaml se accede a ellos mediante alias: $.message.pathParam.id.
Estructura completa de api.yaml
Un fichero api.yaml de una API tiene tres secciones principales: before, endpoints y after.
key: rutas-en-bici
before:
CacheDisabled:
directive: CacheDisabled
PropagateCorrelationId:
directive: PropagateCorrelationId
after:
OnError:
directive: OnError
groups:
- ERROR_FLOW
Log:
directive: Log
groups:
- AFTER_FLOW
endpoints:
get /:
RateLimit:
directive: RateLimit
path: get_home
dayTotal: 80000
dayIp: 10000
minuteTotal: 400
minuteIp: 45
GetProvinces:
directive: Pull
host: $.memory.hefesto-localhost
path: /geo-bike-routes/provinces
target: provinces
cache: 31536000
View:
directive: View
name: home
staticBasePath: $.map.main.staticBasePath
css:
- bootstrap.min
js:
- bootstrap.bundle.min
- Search
- home
fragments:
- footer
data:
provinces: $.memory.provinces
Flujo de ejecución
Al recibir una petición HTTP, las directivas se ejecutan en este orden:
- Before: se ejecutan las directivas definidas en
before:. Se suelen usar para tareas transversales que aplican a todos los endpoints:CacheDisabled,PropagateCorrelationId,RateLimit,Authenticate,CheckKey, etc. - Endpoint: se ejecutan las directivas del endpoint concreto que ha recibido la petición, en el orden en que aparecen.
- After: se ejecutan las directivas definidas en
after:, respetando sus grupos. Aquí suele irOnError(grupo ERROR_FLOW) yLog(grupo AFTER_FLOW).
Grupos (groups)
Los grupos alteran el flujo normal de ejecución. Cada directiva puede pertenecer a uno o varios grupos:
- Sin grupo — NORMAL_FLOW: solo se ejecutan si no ha habido una excepción previa. Es el comportamiento por defecto.
- ERROR_FLOW: solo se ejecutan si una directiva anterior ha lanzado una excepción. Útil para capturar errores y devolver una respuesta adecuada.
- AFTER_FLOW: se ejecutan después de enviar la respuesta al cliente. No afectan a la latencia de la petición. Es el lugar ideal para
Log. - QUEUE_FLOW: se ejecutan tras encolar un grupo de directivas (ver jobs).
También puedes crear grupos personalizados y activarlos/desactivarlos desde el estado:
$state->groups()->enable('CUSTOM_NAME');
$state->groups()->disable('ANOTHER_NAME');
$state->groups()->disableAll();
Ejemplo de grupos personalizados:
post /grid:
SetGridFlow:
directive: SetGridFlow
CalculateGrid:
directive: CalculateGrid
groups:
- NORMAL_FLOW
- DIGESTION_REQUEST_FLOW
Connect:
directive: DatabaseConnect
groups:
- DIGESTION_REQUEST_FLOW
SaveGrid:
directive: SaveGrid
groups:
- DIGESTION_REQUEST_FLOW
Push:
directive: Push
path: /jobs/http/digestion
groups:
- DIGESTION_REQUEST_FLOW
PrepareResponse:
directive: ModifyMessage
body: $.memory.response
Comportamiento según grupos — Ejemplo completo
key: mi-api
before:
CheckKey:
directive: CheckKey
expected: $.map.main.key
current: $.message.header.api-key
after:
OnError:
directive: OnError
groups:
- ERROR_FLOW
Log:
directive: Log
groups:
- AFTER_FLOW
endpoints:
get /user/{id}:
Connect:
directive: DatabaseConnect
ReadUser:
directive: ReadUser
id: $.message.pathParams.id
PrepareResponse:
directive: ModifyMessage
headers:
Content-Type: application/json
body: $.memory.user
En una llamada contra GET /user/{id} donde no ocurra ningún error, el flujo será:
- CheckKey (before)
- Connect, ReadUser, ModifyMessage (endpoint)
- OnError → no se ejecuta (está en ERROR_FLOW)
- Log → se ejecuta en AFTER_FLOW, una vez enviada la respuesta
Si se produce un error en ReadUser, se lanza una excepción. Las directivas ModifyMessage y siguientes de NORMAL_FLOW no se ejecutan. OnError captura el error (porque está en ERROR_FLOW) y Log registra el fallo (porque AFTER_FLOW siempre se ejecuta).
Endpoint especial: all /requests
El endpoint all /requests captura todas las peticiones que no hayan sido resueltas por ningún otro endpoint. Es muy útil para dos casos:
- Middleware/proxy: convertir la API en un proxy que reenvíe todo a otro microservicio.
- Página 404: devolver una vista personalizada cuando no se encuentra la ruta.
Ejemplo de proxy total:
all /requests:
Smart:
directive: Smart
Http:
directive: Http
host: $.memory.poems-host
CacheStatic:
directive: CacheStatic
expiresMinutes: 6000
Ejemplo de 404 con vistas:
all /requests:
SetSmartError:
directive: SetSmartError
RateLimit:
directive: RateLimit
path: all_requests
dayTotal: 80000
dayIp: 10000
minuteTotal: 400
minuteIp: 45
ThrowError:
directive: ThrowError
status: 404
message: "Not Found
Puedes combinar all /requests con el resto de endpoints: si una petición no es resuelta por ningún endpoint específico, la captura all /requests para dar una respuesta por defecto.
Uso de parámetros dinámicos
Las directivas reciben parámetros desde el api.yaml mediante alias: valores fijos, de maps, de memory o del message.
get /route/{routeId}:
CalculatePath:
directive: Concat
element1: /geo-bike-routes/route/
element2: $.message.pathParam.routeId
target: routePath
Pull:
directive: Pull
host: $.memory.hefesto-localhost
path: $.memory.routePath
target: route
queryParams:
validated: 'true'
excludingVias: 'true'
En este ejemplo se construye dinámicamente el path a partir del routeId recibido en la URL y se hace una llamada local a otra API.