A programmable HTTP/WebSocket proxy for Ably SDK integration testing. It sits between the SDK under test and the real Ably sandbox, transparently forwarding traffic by default but injecting faults — dropped connections, modified responses, delayed frames, injected protocol messages — when configured with rules.
┌──────────┐ ┌──────────────────────────┐ ┌───────────────┐
│ SDK │──WS/HTTP──▶ uts-proxy │──WSS/HTTPS──▶ Ably Sandbox │
│ under │◀────────── (per-session ports) │◀──────────── (real backend)│
│ test │ │ │ └───────────────┘
└──────────┘ │ Control API (:9100) │
└────────────▲─────────────┘
│
┌────────────┴─────────────┐
│ Test process │
│ (creates sessions, │
│ configures rules, │
│ triggers actions, │
│ inspects traffic logs) │
└──────────────────────────┘
The proxy serves multiple concurrent test sessions, each on its own TCP port. A control API on a dedicated port (default :9100) manages session lifecycle:
- Create a session — bind a port, set the upstream target, optionally configure rules
- SDK connects through the session port using plain HTTP/WS (the proxy handles TLS upstream)
- Rules match on WebSocket frames (by Ably protocol action, channel, direction) or HTTP requests (by method, path) and fire actions — suppress, delay, inject, replace, disconnect, or return fake responses
- Imperative actions let tests trigger faults on demand (disconnect, close, inject a message)
- Traffic logs capture every frame and request for test assertions
- Teardown closes connections, frees the port, and returns the final log
The proxy is protocol-aware: it decodes Ably protocol messages in both JSON and msgpack for rule matching, but forwards raw bytes unchanged.
Prebuilt binaries are available for:
| OS | Architecture |
|---|---|
| Linux | amd64, arm64 |
| macOS | amd64 (Intel), arm64 (Apple Silicon) |
Building from source requires Go 1.22 or later and works on any platform Go supports.
Download the latest release from GitHub Releases, extract it, and place it on your PATH.
go build -o uts-proxy .Start the proxy:
./uts-proxy --port 9100Check health:
curl http://localhost:9100/health
# {"ok":true}Create a session that proxies to the Ably sandbox:
curl -X POST http://localhost:9100/sessions \
-H 'Content-Type: application/json' \
-d '{
"port": 10042,
"target": {
"realtimeHost": "sandbox-realtime.ably.io",
"restHost": "sandbox-rest.ably.io"
},
"rules": [{
"match": {"type": "ws_connect", "count": 1},
"action": {"type": "refuse_connection"},
"times": 1,
"comment": "refuse first connection, then passthrough"
}],
"timeoutMs": 30000
}'
# {"sessionId":"a1b2c3d4","proxy":{"host":"localhost:10042","port":10042}}Point your SDK at the proxy (plain WS/HTTP, no TLS):
ws://localhost:10042/?key=YOUR_KEY&heartbeats=true
http://localhost:10042/channels/test/messages
Inspect the traffic log:
curl http://localhost:9100/sessions/a1b2c3d4/logTeardown the session (returns the final log):
curl -X DELETE http://localhost:9100/sessions/a1b2c3d4See docs/API.md for the complete control API reference, including all endpoints, rule match types, action types, and the event log format.
See docs/DESIGN.md for the original design proposal, including architecture, motivation, and usage patterns.
This project uses Semantic Versioning.
The CHANGELOG contains details of each release. You can also find prebuilt binaries on the GitHub Releases page.
Read the CONTRIBUTING.md guidelines to contribute to this project.
For help or technical support, visit Ably's support page or open an issue on GitHub.