Expand description
Universal gRPC→REST transcoding proxy.
Config-driven: same binary, different YAML = different product proxy. Works with ANY gRPC service via proto descriptors as config.
§Usage
structured-proxy --config sid-proxy.yaml
structured-proxy --config sflow-proxy.yaml§JWT verification
The bearer-token check sits behind hooks::TokenVerifier. A build gets one
of two:
- the built-in verifier (keys from
auth.jwt), whose crypto backend is picked by a feature:rust_crypto(default, pure Rust) oraws_lc_rs(opt-in, constant-time / FIPS-capable, links aws-lc via C FFI). Both may be compiled in at once — Cargo features are additive, so a dependency graph with two dependents asking for different backends unifies into exactly that build.aws_lc_rsthen wins: it is constant-time and free of thersaadvisoryrust_cryptocarries.ProxyServer::from_configsettles that choice for the process; a process where another crate may reachjsonwebtokenbefore any server exists callsinstall_default_crypto_providerfrommaininstead. - an injected one, supplied by the embedder through
ProxyServer::with_token_verifier. Since Cargo unifies features across a whole dependency graph, a backend feature cannot be chosen per binary — injection is how a consumer that needs a different one gets it without deciding for everyone else who links this crate. Such a build takesdefault-features = falseand links no JWT crypto at all.
§Outbound TLS
JWKS fetches and the rate-limit service go over rustls. The crypto provider
is the one the process installed with
rustls::crypto::CryptoProvider::install_default, else the one the crypto
backend feature brings (aws-lc for aws_lc_rs, RustCrypto for
rust_crypto). A build with neither feature links no TLS crypto, and a
config that needs an outbound client then fails at startup unless a
provider is installed first.
Re-exports§
pub use auth::crypto::install_default_crypto_provider;pub use client_address::ClientAddress;pub use received::ReceivedRequest;pub use service::ConnectionInfo;pub use service::ProxyService;
Modules§
- auth
- JWT authentication and route-level authorization.
- client_
address - The client’s address: resolved once per request, before any guard, and forwarded to the upstream by an explicit policy.
- config
- YAML-based proxy configuration.
- hooks
- Framework-agnostic extension points for embedding the proxy.
- oidc
- OpenID Connect discovery surface.
- openapi
- OpenAPI 3.0 spec generation from proto descriptors.
- received
- The HTTP request a transcoded call was made from.
- service
- The proxy as one tower service: native gRPC to the upstream, everything else to the proxy’s routes, and what no route answers to a fallback.
- shield
- Shield: request rate limiting.
- transcode
- REST→gRPC transcoding layer.
- upstream
- The gRPC service the proxy calls.
Structs§
- Proxy
Server - Universal proxy server.
- Serve
Options - How
serve_withruns its listener.
Functions§
- serve
- Serve
serviceonlistener: cleartext HTTP/1.1 and HTTP/2 on the same port, so REST clients and native gRPC clients share it. It runs until the future is dropped, which closes every connection;serve_with_shutdownstops gracefully, andserve_withadds TLS and a connection limit. - serve_
with servewithoptions: TLS termination (mTLS when the config verifies client certificates) and a cap on open connections. Each connection’s service gets its peer, and behind TLS its client certificates, throughProxyService::for_connection. The TLS handshake runs in the connection’s own task, so a slow client does not hold up the others.- serve_
with_ shutdown serve_with, untilsignalresolves; then a graceful shutdown. The listening socket closes, so new connections are refused; a connection still in its TLS handshake or waiting for itsmax_connectionsslot is dropped; every open connection is asked to wind down (HTTP/2 gets a GOAWAY, so its client opens no new streams; HTTP/1.1 closes after the response in progress), and requests and streams in flight finish. The future resolves once every connection has closed, or afterdrain_timeout, closing the ones still open. Dropping it closes every connection at once.