IR
irwinrodriguez.dev
Zuruck zur Dokumentation

Middleware

Middleware in FoxServer sind Komponenten, die Anfragen verarbeiten, bevor oder nachdem sie den Controller erreichen. Sie konnen die eingebauten (JWT, CORS, Protokollierung) verwenden oder eigene schreiben.

JWT — Authentifizierung

Die JWT-Middleware schutzt private Endpunkte. Clients mussen einen gultigen Token im Authorization-Header senden.

Konfiguration in JSON:

"middleware": {
  "auth": {
    "enabled": true,
    "type": "jwt",
    "secret": "your-256-bit-secret-key-base64-encoded",
    "tokenexpirationseconds": 3600,
    "loginendpoint": "auth/login"
  }
}

Authentifizierungsablauf:

  1. Client sendet POST an den Login-Endpunkt mit Anmeldedaten.
  2. Controller validiert Anmeldedaten und generiert einen JWT-Token.
  3. Client speichert den Token und sendet ihn bei nachfolgenden Anfragen.
  4. Middleware fangen die Anfrage ab, validiert den Token vor dem Controller.
  5. Wenn der Token ungultig oder abgelaufen ist, gibt die Middleware automatisch 401 zuruck.

Login-Controller (generiert den 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

Geschutzter Endpunkt (kein zusatzlicher Code erforderlich):

* 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

Die CORS-Middleware antwortet automatisch auf OPTIONS-Preflight-Anfragen und fugt allen Antworten die notwendigen Header hinzu.

{
  "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
OPTIONS/Preflight-Anfragen werden automatisch von der Middleware beantwortet, ohne den Controller zu erreichen.

Protokollierung

Protokolliert automatisch Anfragen, Antworten und Fehler in tagliche Dateien.

  • Simple — eine Zeile pro Anfrage
  • Detailed — vollstandige Informationen einschliesslich Header und Body (nutzlich in der Entwicklung)
  • JSON — strukturiertes Format fur den Einsatz durch Monitoring-Tools

Beispielausgabe (Detailed-Format):

[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

Benutzerdefinierte Middleware (Hooks)

Sie konnen den Anfrage-/Antwortzyklus mit projektweiten Hooks abfangen:

* 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
Hooks sind spezielle Methoden im Root-Controller. .F. in BeforeRequest zurickzugeben bricht die Anfrage ab und gibt automatisch 403 zuruck.

Weiter: Lizenzierung →