From a0ec642ca153752e8e4666bcd2fab4740cc05355 Mon Sep 17 00:00:00 2001 From: Chris Rai Date: Sat, 31 Jan 2026 14:34:45 -0500 Subject: [PATCH] fix: serve index.html for docs directory, update README with testing instructions --- services/gateway/README.md | 61 +++++++++++++++++++---------- services/gateway/handlers/static.go | 23 ++++++++++- 2 files changed, 61 insertions(+), 23 deletions(-) diff --git a/services/gateway/README.md b/services/gateway/README.md index b6b312a..f070ebc 100644 --- a/services/gateway/README.md +++ b/services/gateway/README.md @@ -7,7 +7,7 @@ WebSocket API gateway for vehicle (TRex), HMI, and mobile app connections. - Authenticates WebSocket connections via JWT - Routes messages to Kafka topics - Manages connection state in Redis -- Serves Swagger docs +- Serves AsyncAPI docs ## Ports @@ -18,37 +18,56 @@ WebSocket API gateway for vehicle (TRex), HMI, and mobile app connections. ## WebSocket Endpoints -- `/ws/trex` - Vehicle connections -- `/ws/hmi` - HMI connections -- `/ws/mobile` - Mobile app connections +| Endpoint | Purpose | User-Agent | +|----------|---------|------------| +| `/session` | Vehicle (TRex) and HMI connections | `Fisker Ocean T.Rex x.x.x.x` or `HMI x.x.x.x` | +| `/secret_mobile` | Mobile app connections | `Mobile x.x.x` or `iOS x.x.x` or `Android x.x.x` | + +## API Documentation + +AsyncAPI specs available at `/docs/`: +- `/docs/asyncapi_mobile.yaml` - Mobile API +- `/docs/asyncapi_hmi.yaml` - HMI API +- `/docs/asyncapi_trex.yaml` - T-Rex API +- `/docs/index.html` - Interactive UI + +## Testing WebSocket Connections + +Install websocat: +```bash +brew install websocat +``` + +Test mobile endpoint: +```bash +# Connect to mobile websocket +websocat -H="User-Agent: Mobile 1.0.0" wss://gateway.mini.cloud.fiskerinc.com/secret_mobile + +# Send verify message (after connecting) +{"handler":"verify","data":{"token":""}} +``` + +Test vehicle endpoint (requires VIN in SSL cert or header): +```bash +websocat -H="User-Agent: Fisker Ocean T.Rex 1.0.0.0 ABC123" \ + -H="X-VIN: YH7DR1EA1PA000001" \ + wss://gateway.mini.cloud.fiskerinc.com/session +``` ## Build ```bash -# Local -go build . - -# Docker -docker build -t gateway -f Dockerfile ../.. -``` - -## Run - -```bash -# Required env vars -export KAFKA_HOSTS=localhost:9092 -export REDIS_HOST=localhost -export JWK_URL=https://keycloak.example.com/realms/consumer/protocol/openid-connect/certs - -./gateway +# From cloud-services root +docker build --platform linux/arm64 -t gateway:latest -f services/gateway/Dockerfile . ``` ## Configuration -See `deploy/base/configmap-common.yaml` for all options. +See `deploy/base/config.env` for all environment variables. Key settings: - `KAFKA_HOSTS` - Kafka bootstrap servers - `REDIS_HOST/PORT` - Redis for session state - `JWK_URL` - JWKS endpoint for JWT validation +- `DOCS` - Path to docs directory (default: `/docs`) - `LOG_LEVEL` - debug, info, warn, error diff --git a/services/gateway/handlers/static.go b/services/gateway/handlers/static.go index 512923a..ac1ff46 100644 --- a/services/gateway/handlers/static.go +++ b/services/gateway/handlers/static.go @@ -2,6 +2,8 @@ package handlers import ( "net/http" + "os" + "path" "github.com/fiskerinc/cloud-services/pkg/utils/envtool" ) @@ -12,6 +14,23 @@ func DocsHandler() http.Handler { if fp == "" { return nil } - fs := http.FileServer(http.Dir(fp)) - return fs + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Get the requested path + reqPath := r.URL.Path + if reqPath == "" || reqPath == "/" { + reqPath = "/index.html" + } + + // Build full file path + fullPath := path.Join(fp, reqPath) + + // Check if it's a directory, serve index.html + info, err := os.Stat(fullPath) + if err == nil && info.IsDir() { + fullPath = path.Join(fullPath, "index.html") + } + + http.ServeFile(w, r, fullPath) + }) }