How roxy works
An exchange is one request and its response. Every exchange takes the same path, however roxy is deployed.
Decrypt and parse
On a proxy listener the client sends CONNECT, and roxy terminates the TLS
inside the tunnel with a certificate from its own CA. On a gateway
listener, a load balancer in front has already terminated TLS
(HTTP).
roxy parses each request into one canonical form and sends that form upstream. Ambiguous input is rejected rather than guessed at, so what the addons and rules see is exactly what is forwarded. Bodies stay streams.
Addons
An addon is a WASM component that runs inside roxy or an external service the traffic streams through. Addons run in the order they are configured and can rewrite, hold, answer or block the exchange. Whatever an addon passes on is checked again as strictly as a client request (addon model).
Rules
The rules are a list of allows, and denies that restrict them. A matching deny always wins, and anything no rule allows is denied. The decision to forward is made on the request head. Rules that read bodies or the response are checked again as the bytes stream, and can still stop the exchange (policy evaluation).
secrets:
openai: { env: OPENAI_API_KEY }
rules:
- id: github-reads
when: host under "github.com" and method in [GET, HEAD]
then: allow
- id: openai
when: host == "api.openai.com" and path starts_with "/v1/" and method == POST
then:
- set_header: { authorization: "Bearer ${secret:openai}" } # the client never sees the key
- allow
- id: upload-cap # checked as the body streams
when: host == "api.openai.com" and body.bytes > 10mb
then: { deny: { status: 413 } }Connect
roxy resolves the host itself and checks every address against the address floor before it connects. A name that resolves to a private address is refused unless a rule allows it (upstream, address floor).
Respond
The response comes back the same way: rules that read it are checked, the addons see it, and roxy re-frames it for the client.
Log
Every step writes to the flow log: one JSON line per exchange, naming the rule that decided, the addons that ran and what changed. The log never drops a record. When it falls behind, traffic waits (flow log).
Reloads
The compiled config is swapped in whole when it changes. An exchange finishes under the config it started with (reload). In node mode the config comes from a control plane instead of a file.