Skip to main content

Crate structured_proxy

Crate structured_proxy 

Source
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) or aws_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_rs then wins: it is constant-time and free of the rsa advisory rust_crypto carries. ProxyServer::from_config settles that choice for the process; a process where another crate may reach jsonwebtoken before any server exists calls install_default_crypto_provider from main instead.
  • 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 takes default-features = false and 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§

ProxyServer
Universal proxy server.
ServeOptions
How serve_with runs its listener.

Functions§

serve
Serve service on listener: 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_shutdown stops gracefully, and serve_with adds TLS and a connection limit.
serve_with
serve with options: 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, through ProxyService::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, until signal resolves; then a graceful shutdown. The listening socket closes, so new connections are refused; a connection still in its TLS handshake or waiting for its max_connections slot 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 after drain_timeout, closing the ones still open. Dropping it closes every connection at once.