IR
irwinrodriguez.dev
Back to docs

Advanced Features

FoxServer includes advanced functionality for modern use cases: real-time event streaming, webhooks with retries, hot controller reloading, metrics and Windows service mode.

Server-Sent Events (SSE)

SSE allows the server to push events to the client over a persistent HTTP connection. Ideal for real-time notifications, long operation progress and data feeds.

Enable in JSON:

{ "middleware": { "sse": true } }

Implementation in the controller:

PROCEDURE GetLiveData(req, res) HELP "GET: stream/live public"
    LOCAL i, lcData

    res.header("Content-Type",  "text/event-stream")
       .header("Cache-Control", "no-cache")
       .header("Connection",    "keep-alive")

    FOR i = 1 TO 20
        lcData = '{"tick":' + TRANSFORM(i) + ',"ts":"' + DTOC(DATETIME()) + '"}'
        res.send("data: " + lcData + CHR(13) + CHR(10) + CHR(13) + CHR(10))
        INKEY(1)   && 1-second pause between events
    NEXT
ENDPROC

JavaScript client:

const es = new EventSource('/api/stream/live');
es.onmessage = (e) => {
  const data = JSON.parse(e.data);
  console.log('tick', data.tick, 'at', data.ts);
};
es.onerror = () => es.close();

Webhooks System

FoxServer includes a webhook processor with persistent queue, automatic retries with exponential backoff and HMAC-SHA256 signing.

  • Persistent queue (survives server restarts)
  • Automatic retries with configurable exponential backoff
  • Automatic HMAC-SHA256 signing on each delivery
  • Concurrent workers for parallel deliveries
  • Log of all delivery attempts

Configuration:

"middleware": {
  "webhooks": {
    "enabled": true,
    "global": {
      "retries": 3,
      "timeout": 30,
      "backoff": [5, 15, 30],
      "queue": { "path": "queue/webhooks", "workers": 2 },
      "logging": { "enabled": true, "path": "logs/webhooks/" }
    }
  }
}

Trigger a webhook from a controller:

PROCEDURE PostOrder(req, res) HELP "POST: orders public"
    LOCAL lcOrderId, loEvt, loResp

    lcOrderId = THIS.CreateOrder(req.json)

    * Build the webhook event
    loEvt = THIS.newObject("event,data")
    loEvt.event      = "order.created"
    loEvt.data       = THIS.newObject("orderId,customer,total")
    loEvt.data.orderId   = lcOrderId
    loEvt.data.customer  = req.json.customer
    loEvt.data.total     = req.json.total

    * Queue — FoxServer handles delivery, retries, signing
    THIS.QueueWebhook("https://partner.com/webhooks", "shared-secret", loEvt)

    loResp = THIS.newObject("orderId,status")
    loResp.orderId = lcOrderId
    loResp.status  = "created"
    res.status(201).json(THIS.ToJson(loResp))
ENDPROC

The receiver gets:

POST https://partner.com/webhooks
webhook-id: 550e8400-e29b-41d4-a716-446655440000
webhook-timestamp: 2026-04-11T14:23:45Z
webhook-signature: sha256=hmac-sha256-of-body

{
  "event": "order.created",
  "data": { "orderId": "ORD-001", "customer": "Irwin", "total": 99.99 }
}

Hot Reload

Hot Reload detects changes in the compiled DLL and reloads controllers without restarting the server. In-flight requests finish on the previous version; new requests use the updated version.

How it works:

  1. Edit and save your .prg file in VFP.
  2. WinFx or the VFP compiler regenerates the Interop DLL.
  3. FoxServer detects the change in the DLL file (FileSystemWatcher).
  4. Waits for active requests to finish (graceful drain).
  5. Releases COM references to old controllers.
  6. Loads the new DLL in an isolated AppDomain.
  7. Logs: 'Hot reload complete'.

Enable in JSON:

{
  "hotreload": {
    "enabled": true,
    "watchpaths": ["C:\\projects\\myapi\\build"],
    "excludepatterns": ["*.log", "*.tmp"]
  }
}

Server metrics

The /status endpoint (when enabled) returns the current server state including performance metrics.

GET /status
{
  "status": "ok",
  "version": "0.7.0",
  "license": "Commercial",
  "uptime": "5d 3h 22m",
  "totalRequests": 182043,
  "successRequests": 181998,
  "errorRequests": 45,
  "avgResponseMs": 12,
  "activeConnections": 7,
  "memoryMB": 245
}

Access metrics from a controller:

PROCEDURE GetStatus(req, res) HELP "GET: status public"
    LOCAL loMetrics, loResp
    loMetrics = THIS.GetServerMetrics()
    loResp = THIS.newObject("status,metrics")
    loResp.status  = "ok"
    loResp.metrics = loMetrics
    res.status(200).json(THIS.ToJson(loResp))
ENDPROC

White Label

Allows hiding that the server is built with FoxServer. Useful when distributing a product under your own brand.

{
  "whitelabel": {
    "serverName": "Acme API Gateway",
    "headerTitle": "Acme Corp",
    "hideVersion": true
  }
}

Windows Service mode

FoxServer can be installed as a Windows Service for automatic startup and background execution without a console window.

Commands:

# Install as service
FoxServer.exe --install-service --name "AcmeAPIServer"

# Uninstall service
FoxServer.exe --uninstall-service --name "AcmeAPIServer"

# Manage via Windows Services
services.msc
In service mode, logs are written to the Windows Event Viewer (Application) in addition to the configured log files.

Next: API Reference →