Middleware
El middleware en FoxServer son componentes que procesan las peticiones antes o despues de que lleguen al controlador. Puedes usar los integrados (JWT, CORS, logging) o escribir los tuyos propios.
JWT — Autenticacion
El middleware JWT protege endpoints privados. Los clientes deben enviar un token valido en el header Authorization.
Configuracion en JSON:
"middleware": {
"auth": {
"enabled": true,
"type": "jwt",
"secret": "your-256-bit-secret-key-base64-encoded",
"tokenexpirationseconds": 3600,
"loginendpoint": "auth/login"
}
} Flujo de autenticacion:
- El cliente hace POST al endpoint de login con sus credenciales.
- El controlador valida las credenciales y genera un token JWT.
- El cliente almacena el token y lo envia en peticiones posteriores.
- El middleware intercepta la peticion, valida el token antes de llegar al controlador.
- Si el token es invalido o ha expirado, el middleware devuelve 401 automaticamente.
Controlador de login (genera el token):
PROCEDURE PostLogin(req, res) HELP "POST: auth/login public"
LOCAL lcUser, lcPass, lcToken, loResp
lcUser = req.json.username
lcPass = req.json.password
IF !THIS.ValidateCredentials(lcUser, lcPass)
res.status(401).json('{"error":"Invalid credentials"}')
RETURN
ENDIF
* GenerateJWT is a built-in ApiController method
lcToken = THIS.GenerateJWT(lcUser)
loResp = THIS.newObject("token,expiresin")
loResp.token = lcToken
loResp.expiresin = 3600
res.status(200).json(THIS.ToJson(loResp))
ENDPROC Endpoint protegido (no requiere codigo adicional):
* Omit "public" — JWT middleware runs automatically before this
PROCEDURE GetMyProfile(req, res) HELP "GET: profile"
LOCAL lcUserId, loResp
lcUserId = THIS.GetUserIdFromToken(req)
loResp = THIS.newObject("id,name,email")
loResp.id = lcUserId
loResp.name = THIS.GetUserName(lcUserId)
loResp.email = THIS.GetUserEmail(lcUserId)
res.status(200).json(THIS.ToJson(loResp))
ENDPROC # Request with valid token:
curl http://localhost:8080/api/profile \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
# Request without token → 401 Unauthorized (automatic)
curl http://localhost:8080/api/profile
# {"error":"Unauthorized","message":"Missing or invalid token"} CORS — Cross-Origin
El middleware CORS responde automaticamente a las peticiones preflight OPTIONS y agrega los headers necesarios a todas las respuestas.
{
"allowedorigins": "https://myapp.com,https://admin.myapp.com",
"allowedmethods": "GET,POST,PUT,DELETE,OPTIONS",
"allowedheaders": "Content-Type,Authorization,X-Requested-With"
} # Browser sends preflight:
OPTIONS /api/products HTTP/1.1
Origin: https://myapp.com
Access-Control-Request-Method: POST
# FoxServer responds automatically:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400 Las peticiones OPTIONS/preflight son respondidas automaticamente por el middleware sin llegar al controlador.
Logging
Registra automaticamente peticiones, respuestas y errores en archivos diarios.
- Simple — una linea por peticion
- Detailed — informacion completa incluyendo headers y body (util en desarrollo)
- JSON — formato estructurado para consumo por herramientas de monitoring
Salida de ejemplo (formato Detailed):
[2026-04-11 14:23:45.123] INFO GET /api/v1/products?page=1
Client : 192.168.1.100
Status : 200 OK
Duration : 45ms
Bytes out : 2048
[2026-04-11 14:23:46.456] ERROR POST /api/v1/orders
Client : 192.168.1.100
Status : 500 Internal Server Error
Error : Database connection failed
Duration : 1250ms Middleware personalizado (Hooks)
Puedes interceptar el ciclo de peticion/respuesta con hooks a nivel de proyecto:
* Root controller — hooks apply to all endpoints in this project
DEFINE CLASS AppController AS ApiController OLEPUBLIC
* Runs before EVERY endpoint
FUNCTION BeforeRequest(req, res) AS BOOLEAN
* Example: block specific IPs
IF req.remoteIP == "10.0.0.99"
res.status(403).json('{"error":"Forbidden"}')
RETURN .F. && .F. = stop processing
ENDIF
* Open shared resources
SET DELETED ON
SET EXCLUSIVE OFF
RETURN .T. && .T. = continue to controller
ENDFUNC
* Runs after EVERY response is sent
PROCEDURE AfterResponse(req, res)
* Cleanup, metrics, audit log
THIS.LogAudit(req.method, req.path, res.statusCode, req.remoteIP)
ENDPROC
ENDDEFINE Los hooks son metodos especiales en el controlador raiz. Retornar .F. en BeforeRequest aborta la peticion y devuelve 403 automaticamente.
Siguiente: Licencias →