llm-ready-data / docs /whatsapp-gateway.md
validops-east-1's picture
sure
6cd5bf4
|
Raw
History Blame Contribute Delete
5.4 kB

WhatsApp Service Gateway

The main FastAPI application (port 7860) is the public API gateway. It proxies every request under /api/whatsapp/* to the internal WhatsApp service (a Go/whatsmeow application), which is not exposed publicly.

Client
  |  HTTP
  v
Main FastAPI :7860
  |  /api/whatsapp/...
  v
WhatsApp Service (internal, e.g. http://localhost:8231)
  |
  v
Client

Route mapping

The gateway forwards the full path, query string, HTTP method and body unchanged. All routes require the main application's API key (Authorization: Bearer <API_KEY>).

Client request WhatsApp service call
GET /api/whatsapp/server/ok GET /server/ok (health)
POST /api/whatsapp/instance/create POST /instance/create (admin)
GET /api/whatsapp/instance/status GET /instance/status
POST /api/whatsapp/send/text POST /send/text
DELETE /api/whatsapp/instance/delete/:id DELETE /instance/delete/:id

No path transformation is applied: after the /api/whatsapp prefix is stripped, the rest of the path is appended to WHATSAPP_SERVICE_URL.

Deployment model

Single Docker container (Hugging Face Spaces style): the Go binary is compiled in a multi-stage whatsapp-build stage and embedded in the image at /app/whatsapp-service/server. start.sh launches it as a sibling process and uvicorn is the primary process. The gateway reaches it over loopback (http://127.0.0.1:8231).

A crash of the WhatsApp service does not take the main app down: the gateway returns sanitized 502/503 responses until it recovers (restart loop every 5s, degraded mode).

Gateway behaviour

  • Auth: the gateway requires the main app's Bearer API key. The WhatsApp service's own apikey header is forwarded as-is when provided by the client (per-instance token); otherwise the configured WHATSAPP_SERVICE_GLOBAL_API_KEY is injected (admin routes).
  • Headers: hop-by-hop headers and the gateway's Authorization/Cookie are never forwarded. Response headers are whitelisted — internal Server/content-encoding/hop-by-hop headers never reach the client.
  • Errors: connection failures → 502; timeouts → 504; disabled service → 503. Upstream 4xx/5xx responses are passed through unchanged. Error bodies never contain internal hostnames, URLs, exceptions or stack traces.
  • Payments/streaming: responses are streamed back to the client (media/QR downloads are not buffered).

Configuration

Variable Default Description
WHATSAPP_SERVICE_ENABLED false Enable the gateway routes. start.sh auto-enables it when the binary exists.
WHATSAPP_SERVICE_URL http://localhost:8231 Base URL of the internal WhatsApp service.
WHATSAPP_SERVICE_TIMEOUT 30 Read/write/pool timeout for upstream calls (seconds).
WHATSAPP_SERVICE_CONNECT_TIMEOUT 5 Connect timeout for upstream calls (seconds).
WHATSAPP_SERVICE_GLOBAL_API_KEY (empty) The WhatsApp service GLOBAL_API_KEY, injected as the default apikey header.
WHATSAPP_SERVICE_PORT 8231 Port start.sh uses to launch the embedded binary (SERVER_PORT).
WHATSAPP_SERVICE_BINARY /app/whatsapp-service/server Path to the embedded binary.

WhatsApp service env vars (centralized in the main app)

There is exactly one configuration source: the main application's .env (or the deployment platform's environment). The Go service never reads a .env of its ownstart.sh / the Docker image inject its variables as process environment, and --dev only optionally loads a local .env if one exists. Full reference: the WhatsApp section of .env.example.

Values shared with the main app use the same names (SUPABASE_URL, REDIS_URL, ...). A few names are mapped automatically by start.sh so you only configure one value:

Centralized setting Injected into Go service as
SUPABASE_SERVICE_ROLE_KEY SUPABASE_SERVICE_KEY
WHATSAPP_SERVICE_GLOBAL_API_KEY GLOBAL_API_KEY
WHATSAPP_SERVICE_PORT SERVER_PORT

Other Go-service settings configured centrally: SUPABASE_DB_URL, DATABASE_SAVE_MESSAGES, CLIENT_NAME, CONNECT_ON_STARTUP, DEBUG_ENABLED, LOG_TYPE, WEBHOOK_FILES, OS_NAME, WHATSAPP_VERSION_*, MINIO_*, AMQP_*, NATS_*, WEBHOOK_URL, PROXY_*, API_AUDIO_CONVERTER*, EVENT_IGNORE_*, QRCODE_MAX_COUNT, CHECK_USER_EXISTS, LOG_*.

Configure WHATSAPP_SERVICE_GLOBAL_API_KEY (equivalently GLOBAL_API_KEY) once — it feeds both the gateway's default apikey header and the Go service's authentication.

Health checks

The main app's GET /health now includes a non-fatal whatsapp_service block:

{"configured": true, "reachable": true, "status": "ok"}

The WhatsApp service's own liveness endpoint is exposed through the gateway at GET /api/whatsapp/server/ok.

Testing

python -m pytest tests/test_whatsapp_gateway.py -v

Covers: gateway auth, forwarding (method/path/query/body/headers), apikey injection vs pass-through, upstream 4xx/5xx passthrough, 502/503/504 handling, response-header sanitization and the /health integration.

A full stack test:

docker build -t agentdeck-backend:test .
# run with the WhatsApp env vars above + WHATSAPP_SERVICE_ENABLED=true